Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00030 008535 15046315 na godz. na dobę w sumie
F# 4.0 dla zaawansowanych. Wydanie IV - ebook/pdf
F# 4.0 dla zaawansowanych. Wydanie IV - ebook/pdf
Autor: , , Liczba stron: 560
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-2944-7 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> techniki programowania
Porównaj ceny (książka, ebook (-20%), audiobook).
Język F# jest nowoczesnym, lecz dojrzałym językiem programowania, który zyskuje coraz większą popularność. Ułatwia on korzystanie z kilku paradygmatów programowania: programowania funkcyjnego, obiektowego i imperatywnego. Został zaprojektowany do pisania prostego, solidnego i wydajnego kodu, lecz przydaje się do rozwiązywania złożonych problemów. Kod w F# jest zwięzły i efektywny. Sam F# jest projektem open source, jednak stanowi część platformy .NET. To wszystko czyni z niego język przyszłości!

Trzymasz w ręku kompletny przewodnik po języku F#, w którym wyczerpująco przedstawiono informacje niezbędne do rozpoczęcia pracy w tej technologii. Zwięźle opisano tu paradygmaty obsługiwane przez F#, a następnie pokazano, w jaki sposób można posłużyć się tym językiem do rozwiązywania problemów z siecią, danymi, programowaniem równoległym i analizami. W ten sposób nauczysz się stosować wspomniane paradygmaty i używać kwerend, co pozwoli Ci osiągnąć wysoką produktywność w pisaniu programów dla wielu systemów i technologii.

W tej książce znajdziesz:

Z językiem F# rozwiązywanie problemów stanie się przyjemnością!


Don Syme — jest architektem języka F#. Brał udział w rozwijaniu typów generycznych w C# i technologii .NET Common Language Runtime. W 2015 roku został odznaczony Srebrnym Medalem Królewskiej Akademii Inżynierii.
Adam Granicz — ma 10-letnie doświadczenie w pracy z językiem F#. Pracuje nad narzędziem WebSharper — podstawowym środowiskiem dla języka F#. Regularnie pisze artykuły i zabiera głos na konferencjach.
Antonio Cisternino — jest profesorem Uniwersytetu w Pizie we Włoszech. Zajmuje się głównie metaprogramowaniem i budową architektury systemów. Od kilku lat korzysta z F# i bierze udział w rozwijaniu tego języka.
Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: Expert F# 4.0, 4th Edition Tłumaczenie: Tomasz Walczak ISBN: 978-83-283-2943-0 Original edition copyright © 2015 by Don Syme, Adam Granicz and Antonio Cisternino. All rights reserved Polish edition copyright © 2017 by HELION SA. All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/f4zaa4.zip Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/f4zaa4 Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci O autorach ........................................................................................................ 9 O recenzentach technicznych .......................................................................... 11 Podzi(cid:218)kowania ................................................................................................ 13 Rozdzia(cid:239) 1. Wprowadzenie ................................................................................................ 15 Geneza języka F# ......................................................................................................................... 16 O książce ...................................................................................................................................... 17 Dla kogo przeznaczona jest ta książka? ................................................................................... 20 Rozdzia(cid:239) 2. Pierwszy program w F# — wprowadzenie do j(cid:218)zyka .................................... 21 Tworzenie pierwszego programu w F# ................................................................................... 21 Używanie bibliotek obiektowych w F# .................................................................................... 33 Pobieranie i używanie pakietów ............................................................................................... 35 Dostęp do zewnętrznych danych za pomocą pakietów języka F# ....................................... 37 Uruchamianie serwera WWW i udostępnianie danych za pomocą pakietów języka F# ............................................................................................ 38 Podsumowanie ............................................................................................................................ 39 Rozdzia(cid:239) 3. Wprowadzenie do programowania funkcyjnego ............................................ 41 Liczby i łańcuchy znaków .......................................................................................................... 41 Stosowanie instrukcji warunkowych oraz operatorów i || ............................................ 44 Definiowanie funkcji rekurencyjnych ..................................................................................... 44 Listy .............................................................................................................................................. 46 Opcje ............................................................................................................................................ 49 Wprowadzenie do dopasowywania do wzorca ...................................................................... 50 Wprowadzenie do wartości w postaci funkcji ........................................................................ 54 Podsumowanie ............................................................................................................................ 63 Rozdzia(cid:239) 4. Wprowadzenie do programowania imperatywnego ......................................... 65 Programowanie funkcyjne a programowanie imperatywne ................................................ 65 Pętle i iteracje w programowaniu imperatywnym ................................................................. 66 Używanie modyfikowalnych rekordów .................................................................................. 68 Poleć książkęKup książkę SPIS TRE(cid:165)CI Używanie modyfikowalnych wiązań let .................................................................................. 70 Praca z tablicami ......................................................................................................................... 71 Wprowadzenie do imperatywnych kolekcji platformy .NET .............................................. 74 Wyjątki i ich kontrolowanie ..................................................................................................... 78 Wywoływanie efektów ubocznych — podstawowe operacje wejścia – wyjścia ................ 81 Łączenie programowania funkcyjnego z wydajnymi wstępnymi obliczeniami i pamięcią podręczną z programowania imperatywnego ................................................ 84 Łączenie podejścia funkcyjnego z imperatywnym — programowanie funkcyjne z efektami ubocznymi ...................................................... 91 Podsumowanie ............................................................................................................................ 95 Rozdzia(cid:239) 5. Typy w programowaniu funkcyjnym ............................................................... 97 Przegląd wybranych prostych definicji typów ....................................................................... 97 Wprowadzenie do typów generycznych ............................................................................... 102 Pisanie kodu w wersji generycznej ......................................................................................... 110 Więcej o typach różnego rodzaju ........................................................................................... 115 Wprowadzenie do tworzenia typów pochodnych ............................................................... 116 Rozwiązywanie problemów z inferencją typów ................................................................... 120 Podsumowanie .......................................................................................................................... 125 Rozdzia(cid:239) 6. Programowanie z wykorzystaniem obiektów ............................................... 127 Wprowadzenie do obiektów i składowych ........................................................................... 127 Używanie klas ............................................................................................................................ 130 Dodawanie innych aspektów notacji obiektowej do typów ............................................... 133 Definiowanie typów obiektowych o modyfikowalnym stanie ........................................... 138 Wprowadzenie do interfejsowych typów obiektowych ...................................................... 141 Inne techniki implementowania obiektów ........................................................................... 146 Łączenie podejścia funkcyjnego i obiektów — zwalnianie zasobów ................................. 151 Rozszerzanie istniejących typów i modułów ........................................................................ 157 Używanie obiektów języka F# i typów platformy .NET ...................................................... 160 Podsumowanie .......................................................................................................................... 163 Rozdzia(cid:239) 7. Hermetyzacja i porz(cid:200)dkowanie kodu ............................................................ 165 Ukrywanie elementów ............................................................................................................. 165 Porządkowanie kodu za pomocą przestrzeni nazw i modułów ......................................... 170 Projekty, podzespoły i kolejność kompilacji ......................................................................... 174 Posługiwanie się plikami z sygnaturami ............................................................................... 179 Ponowne wykorzystanie kodu ................................................................................................ 181 Tworzenie i udostępnianie pakietów ..................................................................................... 181 Podsumowanie .......................................................................................................................... 182 Rozdzia(cid:239) 8. Praca z danymi tekstowymi .......................................................................... 183 Budowanie łańcuchów znaków i formatowanie danych .................................................... 183 Parsowanie łańcuchów znaków i danych tekstowych ......................................................... 188 Stosowanie wyrażeń regularnych ........................................................................................... 190 Używanie XML-a do reprezentowania formatów konkretnych ........................................ 195 Użycie JSON-a do reprezentowania formatów konkretnych ............................................ 201 Rekurencyjne parsowanie zstępujące .................................................................................... 204 Parsowanie i formatowanie binarne ...................................................................................... 207 Podsumowanie .......................................................................................................................... 211 4 Poleć książkęKup książkę SPIS TRE(cid:165)CI Rozdzia(cid:239) 9. Praca z sekwencjami i danymi o strukturze drzewiastej ............................... 213 Wprowadzenie do sekwencji .................................................................................................. 213 Więcej o pracy z sekwencjami ................................................................................................ 219 Struktura poza sekwencjami — modelowanie dziedzin ..................................................... 227 Wzorce aktywne — widoki danych strukturalnych ............................................................ 234 Sprawdzanie równości, haszowanie i porównywanie ......................................................... 239 Wywołania ogonowe i programowanie rekurencyjne ........................................................ 244 Podsumowanie .......................................................................................................................... 251 Rozdzia(cid:239) 10. Programowanie z u(cid:285)yciem liczb i wykresy .................................................... 253 Wprowadzenie do FsLab ......................................................................................................... 253 Tworzenie podstawowych wykresów za pomocą biblioteki FSharp.Charting ................ 254 Podstawowe literały i typy liczbowe ...................................................................................... 255 Sekwencje, statystyka i kody liczbowe ................................................................................... 259 Statystyki, algebra liniowa i rozkłady w bibliotece Math.NET .......................................... 266 Szeregi czasowe, ramki danych i biblioteka Deedle ............................................................. 271 Jednostki miary ......................................................................................................................... 273 Podsumowanie .......................................................................................................................... 279 Rozdzia(cid:239) 11. Programowanie reaktywne, asynchroniczne i równoleg(cid:239)e ............................ 281 Wprowadzenie do terminologii ............................................................................................. 282 Zdarzenia ................................................................................................................................... 283 Operacje asynchroniczne ........................................................................................................ 286 Agenty ........................................................................................................................................ 296 Przykład: asynchroniczny agent do obsługi robota internetowego .................................. 301 Współbieżność oparta na współużytkowanej pamięci ........................................................ 305 Podsumowanie .......................................................................................................................... 310 Rozdzia(cid:239) 12. Programowanie symboliczne z u(cid:285)yciem danych strukturalnych .................... 311 Sprawdzanie układów za pomocą rachunku zdań ............................................................... 311 Upraszczanie wyrażeń i różniczkowanie ............................................................................... 325 Podsumowanie ........................................................................................................................... 336 Rozdzia(cid:239) 13. Integrowanie zewn(cid:218)trznych danych i us(cid:239)ug .................................................. 337 Podstawowe żądania REST ..................................................................................................... 338 Wprowadzenie do kwerend .................................................................................................... 341 Inne możliwości związane z SQL-em .................................................................................... 346 Podsumowanie .......................................................................................................................... 353 Rozdzia(cid:239) 14. Budowanie inteligentnych aplikacji sieciowych ............................................ 355 Bezpośrednie udostępnianie treści w sieci ............................................................................ 355 Rozwijanie aplikacji sieciowych z rozbudowanym klientem za pomocą platformy WebSharper ................................................................................... 360 Podsumowanie .......................................................................................................................... 406 Rozdzia(cid:239) 15. Wizualizacje i graficzny interfejs u(cid:285)ytkownika .............................................. 407 Wprowadzenie do biblioteki Eto ............................................................................................ 407 Jak błyskawicznie zbudować aplikację „Witaj, świecie!”? ................................................... 408 Budowa aplikacji graficznej .................................................................................................... 409 5 Poleć książkęKup książkę SPIS TRE(cid:165)CI Łączenie kontrolek i menu ...................................................................................................... 410 Łączenie elementów w interfejs użytkownika ...................................................................... 413 Rysowanie aplikacji .................................................................................................................. 416 Tworzenie przeglądarki fraktali ze zbioru Mandelbrota ....................................................... 420 Pisanie własnych kontrolek ..................................................................................................... 431 Świat, wygląd i układy współrzędnych .................................................................................. 435 Lekkie kontrolki ........................................................................................................................ 444 Podsumowanie .......................................................................................................................... 450 Rozdzia(cid:239) 16. Programowanie zorientowane na j(cid:218)zyk ........................................................ 451 Wyrażenia reprezentujące obliczenia .................................................................................... 452 Używanie mechanizmu refleksji w F# ................................................................................... 466 Cytowania w języku F# ............................................................................................................ 470 Tworzenie dostawców typów w F# ........................................................................................ 474 Podsumowanie .......................................................................................................................... 476 Rozdzia(cid:239) 17. Biblioteki i wspó(cid:239)dzia(cid:239)anie ............................................................................ 477 Typy, pamięć i współdziałanie ................................................................................................ 477 Biblioteki — ogólny przegląd ................................................................................................... 478 Używanie typów systemowych ............................................................................................... 481 Inne struktury danych z języka F# i platformy .NET .......................................................... 482 Nadzorowanie i izolowanie wykonywania kodu ................................................................. 484 Dodatkowe biblioteki związane z refleksją ........................................................................... 484 Na zapleczu — współdziałanie z C# i innymi językami platformy .NET ......................... 487 Współdziałanie z językami C i C++ za pomocą technologii PInvoke .............................. 490 Podsumowanie .......................................................................................................................... 500 Rozdzia(cid:239) 18. Pisanie i testowanie kodu w F# ................................................................... 501 Pisanie kodu .............................................................................................................................. 501 Efektywne używanie F# Interactive ....................................................................................... 507 Używanie diagnostyki z użyciem śledzenia kodu ................................................................ 510 Debugowanie kodu z użyciem środowiska IDE ................................................................... 513 Testowanie kodu ....................................................................................................................... 516 Podsumowanie .......................................................................................................................... 521 Rozdzia(cid:239) 19. Projektowanie bibliotek j(cid:218)zyka F# ............................................................... 523 Projektowanie standardowych bibliotek platformy .NET .................................................. 524 Metodyka projektowania funkcyjnego .................................................................................. 528 Dobry projekt bibliotek w F# .................................................................................................. 530 Wybrane zalecane idiomy ....................................................................................................... 537 Podsumowanie .......................................................................................................................... 539 Krótki przewodnik po j(cid:218)zyku F# ................................................................... 541 Komentarze i atrybuty ............................................................................................................. 541 Typy podstawowe i literały ..................................................................................................... 541 Typy ............................................................................................................................................ 542 Wzorce i dopasowywanie ........................................................................................................ 542 Funkcje, kompozycja i potoki ................................................................................................. 543 Wiązanie i sterowanie przepływem ....................................................................................... 543 Ddodatek 6 Poleć książkęKup książkę SPIS TRE(cid:165)CI Wyjątki ....................................................................................................................................... 544 Krotki, tablice, listy i kolekcje ................................................................................................. 544 Operatory ................................................................................................................................... 545 Definicje typów i obiekty ......................................................................................................... 546 Przestrzenie nazw i moduły .................................................................................................... 547 Przepływy pracy i wyrażenia reprezentujące sekwencje .......................................................... 548 Kwerendy i cytowania .............................................................................................................. 549 Skorowidz .................................................................................................... 551 7 Poleć książkęKup książkę SPIS TRE(cid:165)CI 8 Poleć książkęKup książkę R O Z D Z I A (cid:146) 2 (cid:132) (cid:132) (cid:132) Pierwszy program w F# — wprowadzenie do j(cid:218)zyka W tym rozdziale opisaliśmy proste interaktywne programowanie z użyciem F#. Najpierw pobierz F# z witryny http://fsharp.org i zainstaluj go (jeśli jeszcze tego nie zrobiłeś). W dalszych podrozdziałach używane jest narzędzie F# Interactive (fsi.exe lub fsharpi). Pozwala ono interaktywnie wykonywać fragmenty kodu w F#. Jest to wygodne w trakcie eksplorowania języka. W niniejszym rozdziale zobaczysz przykłady najważniejszych konstruktów języka F# i poznasz najistotniejsze biblioteki. Tworzenie pierwszego programu w F# Na listingu 2.1 pokazaliśmy pierwszy kompletny program w F#. Możliwe, że początkowo go nie zrozumiesz. Jednak pod listingiem kod jest objaśniony krok po kroku. Listing 2.1. Analizowanie łańcucha znaków pod kątem powtarzających się słów /// Podział łańcucha znaków na słowa w miejscach występowania spacji let splitAtSpaces (text: string) = text.Split | Array.toList /// Analizowanie łańcucha znaków pod kątem powtarzających się słów let wordCount text = let words = splitAtSpaces text let numWords = words.Length let distinctWords = List.distinct words let numDups = numWords - distinctWords.Length (numWords, numDups) /// Analizowanie łańcucha znaków pod kątem powtarzających się słów i wyświetlanie wyników let showWordCount text = let numWords, numDups = wordCount text printfn -- Liczba s(cid:239)ów w tek(cid:258)cie: d numWords printfn -- Liczba powtórze(cid:241): d numDups Wklej ten program do narzędzia F# Interactive. Możesz je uruchomić w następujący sposób: (cid:120) Jeśli używasz wiersza poleceń lub terminalu w systemie Linux albo Mac OS X, wywołaj w danym narzędziu polecenie fsharpi i wklej kod. Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH (cid:120) Jeżeli pracujesz w systemie Windows, wywołaj polecenie fsi.exe w wierszu poleceń dla programistów i wklej kod. (cid:120) Jeśli posługujesz się Emacsem, zainstaluj pakiet fsharp-mode z repozytorium MELPA, zastosuj kombinacje klawiszy Ctrl+c i Ctrl+s, aby uruchomić narzędzie F# Interactive, a następnie prześlij kod z bufora do tego narzędzia za pomocą kombinacji klawiszy Ctrl+c i Ctrl+r. (cid:120) Jeżeli korzystasz ze środowiska Visual Studio, otwórz skrypt w języku F# i wybierz opcję F# Interactive w menu View. Aby przenieść kod do narzędzia F# Interactive, zaznacz ten kod i wciśnij kombinację klawiszy Alt+Enter. (cid:120) Jeśli piszesz kod w środowisku Xamarin Studio, utwórz skrypt w języku F# i wybierz opcję F# Interactive w menu Pads. Aby przenieść kod do narzędzia F# Interactive, zaznacz ten kod i wciśnij kombinację klawiszy Ctrl+Enter. Narzędzia do edycji kodu w F# są też dostępne w innych edytorach, takich jak Atom i Sublime Text 3. Jeśli pracujesz w wierszu poleceń, pamiętaj, aby wpisać ;; w celu zakończenia trybu interaktywnego wprowadzania instrukcji. W Visual Studio i Xamarin Studio oraz innych środowiskach interaktywnych nie jest to konieczne — można w nich przesyłać tekst za pomocą podanych wcześniej kombinacji klawiszy. (cid:132) Wskazówka Gdy korzystasz ze (cid:258)rodowiska IDE (ang. Integrated Development Environment), zwykle mo(cid:285)esz uruchomi(cid:202) narz(cid:218)dzie F# Interactive za pomoc(cid:200) skrótu. Na przyk(cid:239)ad w (cid:258)rodowisku Visual Studio mo(cid:285)esz wybra(cid:202) opcj(cid:218) F# Interactive w menu View lub wcisn(cid:200)(cid:202) kombinacj(cid:218) klawiszy Ctrl+Alt+F, gdy otwarty jest plik lub skrypt w j(cid:218)zyku F#. Pojawi si(cid:218) wtedy okno narz(cid:218)dzia F# Interactive i b(cid:218)dziesz móg(cid:239) rozpocz(cid:200)(cid:202) przesy(cid:239)anie tekstu do niego; wymaga to zaznaczenia tekstu i wci(cid:258)ni(cid:218)cia kombinacji Alt+Enter. Uruchom narz(cid:218)dzie F# Interactive w opisany wcze(cid:258)niej sposób F# Interactive version xx.x.xxxxx.x (Tu wy(cid:258)wietlane s(cid:200) zale(cid:285)ne od wersji informacje o narz(cid:218)dziu) For help type #help;; zastosuj polecenie wysy(cid:239)ania kodu do narz(cid:218)dzia lub wklej pokazany wcze(cid:258)niej program ;; val splitAtSpaces : text:string - string list val wordCount : text:string - int * int val showWordCount : text:string - unit Tu F# Interactive informuje o typach funkcji splitAtSpaces, wordCount i showWordCount (więcej o typach dowiesz się już wkrótce). Słowo kluczowe val to skrót od value (czyli „wartość”). W programowaniu w F# funkcje są traktowane jak wartości, co opisaliśmy w rozdziale 3. Ponadto narzędzie F# Interactive czasem wyświetla więcej informacji, niż pokazaliśmy w tej książce (na przykład wewnętrzne szczegóły dotyczące wygenerowanych wartości). Jeśli chcesz wypróbować przedstawione fragmenty kodu, możesz pominąć dodatkowe informacje. Na razie zobacz, jak zastosować interaktywnie funkcję wordCount: let (numWords,numDups) = wordCount All the king s horses and all the king s men ;; val numWords : int = 9 val numDups : int = 2 W tym kodzie pokazaliśmy efekt wykonania funkcji wordCount i powiązania dwóch zwracanych przez nią wyników z nazwami numWords i numDups. Analiza wyników pozwala zobaczyć, że dany tekst 22 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA zawiera dziewięć słów. Dwa z nich się powtarzają, a siedem występuje tylko raz. Funkcja showWordCount wyświetla wyniki jako efekt uboczny działania zamiast zwracać je jako wartość: showWordCount Couldn t put Humpty together again ;; -- Liczba s(cid:239)ów w tek(cid:258)cie: 5 -- Liczba powtórze(cid:241): 0 Na podstawie danych wyjściowych można w przybliżeniu stwierdzić, jak kod działa. Teraz przyjrzyjmy się programowi dokładnie. Dokumentowanie kodu Zacznijmy od definicji funkcji wordCount z listingu 2.1. Pierwszy wiersz definicji nie jest kodem, lecz komentarzem: /// Analizowanie łańcucha znaków pod kątem powtarzających się słów Komentarze to wiersze rozpoczynające się od znaków // lub bloki umieszczone między sekwencjami (* i *). Wiersze rozpoczynające się od trzech ukośników (///) to komentarze XMLDoc, w których w razie potrzeby można umieszczać dodatkowe znaczniki XML-owe. Komentarze z programu można zapisać w jednym pliku .xml i przetwarzać za pomocą dodatkowych narzędzi. Używanie instrukcji let Przyjrzyj się teraz dwóm pierwszym wierszom funkcji wordCount z listingu 2.1. Te wiersze definiują funkcję wordCount i lokalną wartość words. W obu przypadkach używane jest słowo kluczowe let: let wordCount text= let words = ... Słowo kluczowe let to najważniejsza instrukcja, jaką będziesz stosować, programując w F#. Służy ona do definiowania danych, obliczanych wartości i funkcji. Po lewej stronie instrukcji let często znajduje się prosty identyfikator, można tam jednak umieszczać także wzorce (przykłady znajdziesz w punkcie „Używanie krotek” w dalszej części rozdziału) lub nazwę funkcji z listą nazw argumentów — tak jak w przypadku funkcji wordCount przyjmującej jeden argument, text. Po prawej stronie instrukcji let, czyli po znaku =, znajduje się wyrażenie. Warto(cid:258)ci i niemodyfikowalno(cid:258)(cid:202) W innych j(cid:218)zykach warto(cid:258)(cid:202) (ang. value) lokalna jest nazywana zmienn(cid:200) (ang. variable) lokaln(cid:200). W F# nie mo(cid:285)na jednak modyfikowa(cid:202) warto(cid:258)ci lokalnych po ich zainicjowaniu, chyba (cid:285)e dana warto(cid:258)(cid:202) lokalna jest jawnie opatrzona modyfikatorem mutable (do tego tematu wrócimy w rozdziale 4.). Dlatego programi(cid:258)ci j(cid:218)zyka F# i autorzy jego specyfikacji wol(cid:200) zwykle pos(cid:239)ugiwa(cid:202) poj(cid:218)ciem „warto(cid:258)(cid:202)” zamiast „zmienna”. W rozdziale 4. zobaczysz, (cid:285)e dane po(cid:258)rednio wskazywane przez warto(cid:258)ci lokalne mog(cid:200) by(cid:202) modyfikowalne, nawet je(cid:258)li dana warto(cid:258)(cid:202) lokalna taka nie jest. Na przyk(cid:239)ad warto(cid:258)(cid:202) lokalna b(cid:218)d(cid:200)ca uchwytem do tabeli z haszowaniem nie mo(cid:285)e zosta(cid:202) zmodyfikowana tak, by wskazywa(cid:239)a inn(cid:200) tabel(cid:218). Natomiast zawarto(cid:258)(cid:202) samej tabeli mo(cid:285)na modyfikowa(cid:202), wywo(cid:239)uj(cid:200)c operacje, które dodaj(cid:200) i usuwaj(cid:200) elementy tej tabeli. Liczne warto(cid:258)ci i struktury danych w F# s(cid:200) jednak ca(cid:239)kowicie niemodyfikowalne (ang. immutable). Oznacza to, 23 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH (cid:285)e ani okre(cid:258)lona warto(cid:258)(cid:202) lokalna, ani dane, które ona wskazuje, nie mog(cid:200) zosta(cid:202) zmienione za pomoc(cid:200) zewn(cid:218)trznych modyfikacji. Takie dane nazywane s(cid:200) zwykle warto(cid:258)ciami niemodyfikowalnymi. Na przyk(cid:239)ad wszystkie podstawowe typy z platformy .NET (m.in. liczby ca(cid:239)kowite, (cid:239)a(cid:241)cuchy znaków i warto(cid:258)ci typu System.DateTime) s(cid:200) niemodyfikowalne. Ponadto w bibliotece j(cid:218)zyka F# zdefiniowane s(cid:200) ró(cid:285)ne niemodyfikowalne struktury danych, na przyk(cid:239)ad Set i Map, oparte na drzewach binarnych. Pakiet System.Collections.Immutable z repozytorium NuGet obejmuje definicje znacznie wi(cid:218)kszej liczby niemodyfikowalnych typów. Warto(cid:258)ci niemodyfikowalne maj(cid:200) wiele zalet. Pocz(cid:200)tkowo definiowanie warto(cid:258)ci, których nie da si(cid:218) zmieni(cid:202), mo(cid:285)e wydawa(cid:202) si(cid:218) dziwne. Jednak wiedza o tym, (cid:285)e warto(cid:258)(cid:202) jest niemodyfikowalna, sprawia, i(cid:285) rzadko trzeba zastanawia(cid:202) si(cid:218) nad to(cid:285)samo(cid:258)ci(cid:200) obiektu (ang. object identity). Niemodyfikowalne warto(cid:258)ci mo(cid:285)na przekazywa(cid:202) do funkcji i mie(cid:202) przy tym pewno(cid:258)(cid:202), (cid:285)e nie zostan(cid:200) zmienione. Ponadto mo(cid:285)na przekazywa(cid:202) je mi(cid:218)dzy ró(cid:285)nymi w(cid:200)tkami bez obaw o niebezpieczny wspó(cid:239)bie(cid:285)ny dost(cid:218)p do nich (to zagadnienie opisali(cid:258)my w rozdziale 11.). Omówienie typów F# to język z kontrolą typów. Dlatego uzasadnione jest pytanie o typ funkcji wordCount. Narzędzie F# Interactive już go wyświetliło: val wordCount : text:string - int * int Wynika z tego, że funkcja wordCount przyjmuje jeden argument typu string i zwraca wartości typu int * int, co w F# oznacza parę liczb całkowitych. Symbol - informuje, że wordCount to funkcja. W programie nie podano jawnie typu argumentu text, ponieważ typ funkcji wordCount jest określany na podstawie definicji w wyniku inferencji. Inferencję typów opisaliśmy w ramce „Co to jest inferencja typów?”, a także szczegółowo w dalszych rozdziałach. Typy w F# są istotne z różnych powodów (cid:650) od wydajności, przez produktywność pisania kodu, po współdziałanie z innymi technologiami. Typy pomagają strukturyzować biblioteki, radzić sobie ze złożonością interfejsów API i dodawać ograniczenia w kodzie, które zagwarantują, że będzie on prawidłowy i będzie działał wydajnie. System typów w F# (inaczej niż w wielu innych językach z kontrolą typów) jest jednocześnie prosty i daje duże możliwości. Pod wieloma względami jest też piękny. Jest tak, ponieważ stosowane są w nim jednolite i umożliwiające łączenie konstrukty, na przykład krotki i funkcje, pozwalające tworzyć zwięzłe i opisowe typy. Ponadto inferencja typów sprawia, że prawie nigdy nie trzeba zapisywać typów w programie, choć czasem ich podawanie jest przydatne. W tabeli 2.1 wymieniliśmy niektóre spośród najważniejszych sposobów tworzenia typów. Są to dostępne w F# techniki definiowania nowych typów. W rozdziałach 3. i 4. szczegółowo opisaliśmy wszystkie te techniki. Niektóre konstruktory typów, na przykład list i option, są generyczne. Oznacza to, że można ich używać do budowania grup typów, tworząc zmienne generyczne (na przykład typów int list, string list, int list list itd.). Do tworzenia typów generycznych można stosować zarówno notację przedrostkową (int list), jak i notację przyrostkową (list int ). Zwyczajowo notację przedrostkową (int list) stosuje się tylko dla typów z rodzin list i option. Zmienne określające typ, na przykład a i T, to miejsca, które można zastąpić dowolnym typem. Typy generyczne i zmienne określające typ opisaliśmy szczegółowo w rozdziałach 3. i 5. 24 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA Tabela 2.1. Wybrane ważne typy i konstruktory oraz odpowiadające im wartości (int to typ reprezentujący liczby całkowite) Rodzina typów typ option typ list Przykłady int option, option int int list, list int typ1 - typ2 int - string typ1 * ... * typN int * string typ[] unit T int[] unit T, a, Klucz, Warto(cid:258)(cid:202) Opis Wartość danego typu lub wartość specjalna None. Np.: Some 3, Some 3 , None. Niemodyfikowalna lista powiązana wartości danego typu. Wszystkie elementy listy muszą być tego samego typu. Np.: [], [3;2;1]. Typ funkcji reprezentujący wartość w postaci funkcji, która przyjmuje wartości pierwszego typu i oblicza wyniki drugiego typu. Np.: (fun x - x+1). Typ krotki — pary, trójki lub większej liczby typów. Np.: (1, 3 ), (3,2,1). Typ tablicowy do tworzenia „płaskich” i modyfikowalnych kolekcji o stałej wielkości. Typ obejmujący jedną wartość (), podobny do wartości void z wielu języków imperatywnych. Zmienna określająca typ stosowana w kodzie generycznym. Co to jest inferencja typów? Inferencja typów polega na analizowaniu kodu w celu ustalenia ogranicze(cid:241) na podstawie sposobu u(cid:285)ywania ró(cid:285)nych nazw. Ograniczenia s(cid:200) ustalane dla ka(cid:285)dego pliku (w uruchamianym w wierszu polece(cid:241) kompilatorze j(cid:218)zyka F#) i dla ka(cid:285)dej wprowadzonej porcji kodu (w narz(cid:218)dziu F# Interactive). Te ograniczenia musz(cid:200) by(cid:202) spójne. Gwarantuje to, (cid:285)e w programie typy s(cid:200) odpowiednio stosowane. Je(cid:258)li tak nie jest, zg(cid:239)aszany jest b(cid:239)(cid:200)d typów. Ograniczenia s(cid:200) ustalane od góry do do(cid:239)u, od lewej do prawej i od zewn(cid:200)trz do wewn(cid:200)trz. Jest to istotne, poniewa(cid:285) w niektórych sytuacjach kolejno(cid:258)(cid:202) inferencji wp(cid:239)ywa na jej wynik. Inferencja typów skutkuje automatycznym uogólnieniem kodu, dzi(cid:218)ki czemu mo(cid:285)na go ponownie wykorzysta(cid:202) i jest w oczywisty sposób generyczny. Stosowane s(cid:200) odpowiednie typy generyczne, a programista nie musi ich jawnie zapisywa(cid:202). Automatyczne uogólnienie to wa(cid:285)ny czynnik pozwalaj(cid:200)cy pisa(cid:202) zwi(cid:218)z(cid:239)y i jednocze(cid:258)nie mo(cid:285)liwy do ponownego wykorzystania kod z kontrol(cid:200) typów. Wi(cid:218)cej o automatycznym uogólnianiu dowiesz si(cid:218) z rozdzia(cid:239)u 5. Wywoływanie funkcji Funkcje są istotą większości kodu pisanego w F#. Nie jest zaskoczeniem, że pierwszą rzeczą, jaką robi funkcja wordCount, jest wywołanie innej funkcji. Tu jest nią splitAtSpaces, czyli pierwsza funkcja zdefiniowana w programie: let wordCount text= let words = splitAtSpaces text 25 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH Przyjrzyjmy się najpierw funkcji splitAtSpaces w narzędziu F# Interactive: splitAtSpaces witaj, (cid:258)wiecie ;; val it : string list = [ witaj, ; (cid:258)wiecie ] Widać tu, że funkcja splitAtSpaces dzieli podany tekst na słowa w miejscach występowania spacji. W przykładowym kodzie występują też: (cid:120) literały znakowe, na przykład i a ; (cid:120) literały łańcuchowe, na przykład witaj, (cid:258)wiecie ; (cid:120) listy literałów łańcuchowych, na przykład zwrócona wartość [ witaj, ; (cid:258)wiecie ]. Literały i listy omówiliśmy szczegółowo w rozdziale 3. Listy to ważna struktura danych w F#. W tej książce znajdziesz wiele przykładów ich zastosowań. Prosta składnia Kompilator języka F# i narzędzie F# Interactive uwzględniają wcięcia w kodzie w F#, aby określić, gdzie konstrukty zaczynają się i kończą. Reguły stosowania wcięć są bardzo intuicyjne. Opisaliśmy je w dodatku, który stanowi przewodnik po składni języka F#. Na listingu 2.2 pokazaliśmy wersję funkcji wordCount, w której za pomocą słowa kluczowego in jawnie określany jest zasięg wszystkich nazw. Listing 2.2. Wersja funkcji wordCount, w której jawnie używane są słowa kluczowe „in” /// Analizowanie łańcucha znaków pod kątem powtarzających się słów let wordCount text = let words = splitAtSpaces text in let distinctWords = List.distinct words in let numWords = words.Length in let numDups = numWords - distinctWords.Length in (numWords, numDups) Dwa średniki (;;) są konieczne do kończenia kodu wprowadzanego w F# Interactive. Jeśli używasz środowiska IDE, na przykład Visual Studio, zwykle średniki są dodawane automatycznie po zaznaczeniu i uruchomieniu kodu. W tej książce podwójne średniki są pokazywane w interaktywnie wykonywanych fragmentach kodu, ale już nie w większych przykładach. Czasem wygodne jest zapisywanie definicji let w jednym wierszu. W tym celu należy oddzielić wyrażenie od samej definicji słowem kluczowym in. Oto przykład: let powerOfFour n = let nSquared = n * n in nSquared * nSquared A to przykład zastosowania tej funkcji: powerOfFour 3;; val it : int = 81 Zapis let wzo = wyr1 in wyr2 to podstawowy konstrukt języka. Człon wzo oznacza wzorzec, a wyr1 i wyr2 to wyrażenia. Kompilator języka F# dodaje słowo kluczowe in, jeśli wyr2 jest wyrównane w pionie względem słowa kluczowego let z następnego wiersza. 26 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA (cid:132) Wskazówka Zalecamy stosowanie w kodzie pisanym w j(cid:218)zyku F# wci(cid:218)(cid:202) w postaci czterech spacji. U(cid:285)ywanie tabulacji jest niedozwolone. Narz(cid:218)dzia obs(cid:239)uguj(cid:200)ce j(cid:218)zyk F# zg(cid:239)aszaj(cid:200) b(cid:239)(cid:200)d po napotkaniu tabulacji. Wi(cid:218)kszo(cid:258)(cid:202) edytorów j(cid:218)zyka F# automatycznie przekszta(cid:239)ca wyst(cid:200)pienia znaku tabulacji na spacje. Zasięg Wartości lokalne, na przykład words i distinctWords, są niedostępne poza ich zasięgiem (ang. scope). Gdy wartości są definiowane za pomocą słowa kluczowego let, ich zasięg to całe wyrażenie podane po definicji, ale z wyłączeniem samej definicji. Poniżej znajdziesz dwie przykładowe błędne definicje, które próbują uzyskać dostęp do wartości poza ich zasięgiem. Widać tu, że definicje let są przetwarzane sekwencyjnie od góry w dół. Pomaga to zagwarantować, że programy są poprawnie zbudowane i pozbawione wielu błędów związanych z niezainicjowanymi wartościami. let badDefinition1 = let words = splitAtSpaces text let text = We three kings words.Length Oto efekt uruchomienia kodu: error FS0039: The value or constructor text is not defined A to następny przykład: let badDefinition2 = badDefinition2 + 1 I efekt jego wykonania: error FS0039: The value or constructor badDefinition2 is not defined W definicjach funkcji można usunąć wartość z zasięgu, deklarując inną wartość o tej samej nazwie. Na przykład poniższa funkcja oblicza wartość (n*n*n*n)+2: let powerOfFourPlusTwo n = let n = n * n let n = n * n let n = n + 2 n Ten kod to odpowiednik następującego zapisu: let powerOfFourPlusTwo n = let n1 = n * n let n2 = n1 * n1 let n3 = n2 + 2 n3 Usunięcie wartości z zasięgu nie zmienia pierwotnej wartości. Sprawia jedynie, że nazwa danej wartości nie jest dostępna w bieżącym zasięgu. Nie należy nadużywać tej techniki. Ponieważ wiązania tworzone za pomocą instrukcji let to odmiana wyrażenia, takie polecenia można zagnieżdżać. Oto przykład: let powerOfFourPlusTwoTimesSix n = let n3 = 27 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH let n1 = n * n let n2 = n1 * n1 n2 + 2 let n4 = n3 * 6 n4 Tu n1 i n2 to wartości zdefiniowane lokalnie za pomocą instrukcji let w wyrażeniu definiującym wartość n3. Tych wartości lokalnych nie można stosować poza ich zasięgiem. Na przykład poniższy kod spowoduje zgłoszenie błędu: let invalidFunction n = let n3 = let n1Inner = n + n let n2Inner = n1Inner * n1Inner n1Inner * n2Inner let n4 = n1Inner + n2Inner + n3 // Błąd! Wartość n3 znajduje się w zasięgu, ale // pozostałe wartości są poza zasięgiem! n4 Zasięg lokalny jest wykorzystywany w F# do wielu celów — zwłaszcza do ukrywania szczegółów implementacji, których nie chcesz ujawniać poza funkcjami lub obiektami. Zagadnienie to opisaliśmy szczegółowo w rozdziale 7. Używanie struktur danych Oto następny fragment kodu: let wordCount text = let words = splitAtSpaces text let distinctWords = List.distinct words ... Ten fragment pokazuje, jak struktury danych są używane w kodzie napisanym w języku F#. Ostatni wiersz ilustruje istotę obliczeń wykonywanych przez funkcję wordCount. Wykorzystano tu funkcję List.distinct z biblioteki języka F#, aby przekształcić podane słowa na listę z niepowtarzającymi się wyrazami. Wyniki działania tej funkcji można zobaczyć za pomocą narzędzia F# Interactive: List.distinct [ b ; a ; b ; b ; c ];; val it : string list = [ b ; a ; c ] List.distinct (List.distinct [ abc ; ABC ]);; val it : string list = [ abc ; ABC ] Warto zwrócić tu uwagę na kilka rzeczy: (cid:120) Narzędzie F# Interactive wyświetla zawartość ustrukturyzowanych wartości (na przykład list). (cid:120) Powtarzające się elementy są w wyniku konwersji usuwane. (cid:120) Elementy z listy zachowują kolejność, ponieważ funkcja List.distinct nie zmienia kolejności niepowtarzających się wartości. (cid:120) W trakcie wyznaczania kolejności i sprawdzania równości w łańcuchach znaków domyślnie uwzględniana jest wielkość liter. 28 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA Nazwa List oznacza moduł języka F# FSharp.Collections.List z podstawowej biblioteki tego języka. Moduł ten obejmuje operacje powiązane z wartościami typu list. Dla typów często tworzone są odrębne moduły zawierające operacje powiązane z danym typem. Wszystkie moduły z należących do przestrzeni nazw FSharp przestrzeni nazw Core, Collections, Text i Control można podawać w postaci jednowyrazowych przedrostków (na przykład List.distinct). Inne moduły z wymienionych przestrzeni nazw to m.in. Set, Option, Map i Array. Funkcję List.distinct dodano w wersji F# 4.0. We wcześniejszych wersjach należy stosować inne rozwiązania, na przykład Set.ofList. Używanie właściwości i notacji z kropką Dwa następne wiersze funkcji wordCount wyznaczają szukany wynik — liczbę powtarzających się słów. Używana jest do tego właściwość Length przetwarzanej wartości: let numWords = words.Length let numDups = numWords - distinctWords.Length F# analizuje nazwy właściwości na etapie kompilacji (lub interaktywnie, jeśli używasz narzędzia F# Interactive; wtedy rozróżnienie na czas kompilacji i czas wykonywania programu nie obowiązuje). W tym celu wykorzystuje znane w czasie kompilacji informacje o typie wyrażenia podanym po lewej stronie kropki. Tu są to wyrażenia words i distinctWords. Niekiedy w kodzie trzeba podać typ, aby dookreślić potencjalnie wieloznaczne nazwy właściwości. Na przykład w poniższym kodzie podano typ, aby określić, że nazwa inp oznacza listę. Dzięki temu system typów języka F# może wywnioskować, że nazwa Length oznacza właściwość powiązaną z wartościami typu list: let length (inp: T list) = inp.Length Tu T oznacza, że funkcja length jest generyczna. Sprawia to, że można ją stosować do list dowolnego typu. Generyczny kod opisaliśmy szczegółowo w rozdziałach 3. i 5. Zastosowanie notacji z kropką wskazuje na to, że F# jest językiem jednocześnie funkcyjnym i obiektowym. Właściwości są rodzajem składowych (jest to ogólna nazwa określająca dowolne cechy powiązane z typem lub wartością). Składowe wskazywane za pomocą przedrostka w postaci nazwy typu to składowe statyczne. Składowe powiązane z konkretną wartością danego typu to składowe instancji. Dostęp do składowych instancji można uzyskać, podając obiekt po lewej stronie kropki. Rozróżnienie na wartości, właściwości i metody znajdziesz dalej w tym rozdziale, a szczegółowe omówienie składowych zawiera rozdział 6. (cid:132) Uwaga Adnotacje okre(cid:258)laj(cid:200)ce typ mog(cid:200) okaza(cid:202) si(cid:218) przydatn(cid:200) dokumentacj(cid:200). Zwykle nale(cid:285)y je dodawa(cid:202) w miejscu deklaracji zmiennej. Czasem jawnie nazwane funkcje działają jak składowe. Wcześniej przedstawiony kod można zapisać też tak: let numWords = List.length words let numDups = numWords - List.length wordSet W kodzie napisanym w języku F# zetkniesz się z oboma stylami. W niektórych bibliotekach języka F# składowe są używane rzadko lub w ogóle się ich nie stosuje. Jednak rozsądne korzystanie ze składowych i właściwości pozwala znacznie ograniczyć konieczność tworzenia trywialnych funkcji get i set w bibliotekach, istotnie poprawić czytelność kodu klienckiego, a także umożliwić programistom, którzy stosują środowiska takie jak Visual Studio, łatwe i intuicyjne przeglądanie podstawowych funkcji rozwijanych bibliotek. 29 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH Jeśli kod nie zawiera adnotacji określających typ, które pozwalają zinterpretować notację z kropką, wystąpi błąd taki jak pokazany poniżej: let length inp = inp.Length;; error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. You can resolve this by adding a type annotation as shown earlier. Używanie krotek Ostatni fragment funkcji wordCount zwraca krotkę składającą się z liczby słów i liczby powtarzających się słów: ... (numWords, numDups) Krotki to najprostsza i jednocześnie bodaj najbardziej przydatna ze wszystkich struktur danych języka F#. Wyrażenie tworzące krotkę to zestaw połączonych wyrażeń dających nowe wyrażenie: let site1 = ( www.cnn.com , 10) let site2 = ( news.bbc.com , 5) let site3 = ( www.msnbc.com , 4) let sites = (site1, site2, site3) Oto typy określone w wyniku inferencji i obliczone wartości: val site1 : string * int = ( www.cnn.com , 10) val site2 : string * int = ( news.bbc.com , 5) val site3 : string * int = ( www.msnbc.com , 4) val sites : (string * int) * (string * int) * (string * int) = (( www.cnn.com , 10), ( news.bbc.com , 5), ( www.msnbc.com , 4)) Krotki można rozbić na tworzące je komponenty na dwa sposoby. W przypadku par (czyli krotek dwuelementowych) można jawnie wywołać funkcje fst (od ang. first, czyli „pierwszy”) i snd (od ang. second, czyli „drugi”). Jak wskazują nazwy, funkcje te pobierają pierwszy i drugi element pary: fst site1;; val it : string = www.cnn.com let relevance = snd site1;; val relevance : int = 10 Funkcje fst i snd są zdefiniowane w bibliotece języka F# i zawsze można z nich korzystać w programach w tym języku. Oto proste definicje tych funkcji: let fst (a, _) = a let snd (_, b) = b Częściej jednak krotki są rozbijane za pomocą wzorców, tak jak w poniższym kodzie: let url, relevance = site1 let siteA, siteB, siteC = sites 30 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA Tu nazwy podane po lewej stronie definicji są wiązane z odpowiednimi elementami podanej po prawej stronie wartości w postaci krotki. Tak więc url przyjmuje wartość www.cnn.com , a relevance — wartość 10. Wartości w postaci krotek mają określony typ. Istnieje dowolna liczba rodzin typów krotek — jedna dla par (przechowujących dwie wartości), jedna dla trójek (przechowujących trzy wartości) itd. Oznacza to, że jeśli spróbujesz zastosować trójkę w miejscu, gdzie oczekiwana jest para, przed uruchomieniem kodu zgłoszony zostanie błąd związany z typami: let a, b = (1, 2, 3);; error FS0001: Type mismatch. Expecting a a * b but given a a * b * c The tuples have differing lengths of 2 and 3 Krotki często są używane do zwracania wielu wartości przez funkcje (tak jak wcześniej w przykładowej funkcji wordCount). Nieraz służą też do przekazywania wielu argumentów do funkcji. Często krotka zwracana przez jedną funkcję staje się krotką przekazywaną do innej funkcji. W poniższym przykładowym kodzie została pokazana inna wersja zdefiniowanej i stosowanej wcześniej funkcji showWordCount: let showResults (numWords, numDups) = printfn -- Liczba s(cid:239)ów w tek(cid:258)cie: d numWords printfn -- Liczba powtórze(cid:241): d numDups let showWordCount text = showResults (wordCount text) Funkcja showResults przyjmuje parę wartości rozbijaną na elementy numWords i numDups. Para danych wyjściowych z funkcji wordCount staje się parą danych wejściowych funkcji showResults. Warto(cid:258)ci i obiekty W F# wszystko jest warto(cid:258)ci(cid:200). W niektórych innych j(cid:218)zykach wszystko jest obiektem. W praktyce s(cid:239)owa te mo(cid:285)esz cz(cid:218)sto stosowa(cid:202) wymiennie, cho(cid:202) programi(cid:258)ci j(cid:218)zyka F# zwykle rezerwuj(cid:200) okre(cid:258)lenie „obiekt” dla warto(cid:258)ci specjalnego rodzaju: (cid:122) warto(cid:258)ci, których obserwowalne w(cid:239)a(cid:258)ciwo(cid:258)ci zmieniaj(cid:200) si(cid:218) w trakcie wykonywania programu (zwykle w wyniku jawnej modyfikacji przechowywanych w pami(cid:218)ci danych lub za pomoc(cid:200) zewn(cid:218)trznych zmian stanu); (cid:122) warto(cid:258)ci, które wskazuj(cid:200) dane lub stany okre(cid:258)laj(cid:200)ce to(cid:285)samo(cid:258)(cid:202) (takie jak unikatowe identyfikatory ca(cid:239)kowitoliczbowe) albo wyznaczaj(cid:200) ogóln(cid:200) to(cid:285)samo(cid:258)(cid:202) obiektu, s(cid:239)u(cid:285)(cid:200)c(cid:200) do odró(cid:285)niania obiektów od innych warto(cid:258)ci identycznych w pozosta(cid:239)ych aspektach; (cid:122) warto(cid:258)ci, które mo(cid:285)na sprawdzi(cid:202), by ustali(cid:202) dodatkowe mechanizmy za pomoc(cid:200) rzutowania, konwersji i interfejsów. F# obs(cid:239)uguje obiekty, ale nie wszystkie warto(cid:258)ci s(cid:200) uznawane za obiekty. Programowanie w F# nie jest zorientowane obiektowo. J(cid:218)zyk ten umo(cid:285)liwia jednak programowanie obiektowe i pozwala korzysta(cid:202) z obiektów tam, gdzie s(cid:200) najbardziej przydatne. W rozdziale 4. omówili(cid:258)my szczegó(cid:239)owo to(cid:285)samo(cid:258)(cid:202) i modyfikowanie warto(cid:258)ci. 31 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH Używanie kodu imperatywnego Zdefiniowane w poprzednim punkcie funkcje showWordCount i showResults wyświetlają wyniki za pomocą funkcji bibliotecznej printfn: printfn -- Liczba s(cid:239)ów w tek(cid:258)cie: d numWords printfn -- Liczba powtórze(cid:241): d numDups Jeśli znasz język OCaml, C lub C++, funkcja printfn będzie wyglądała znajomo (jak odmiana funkcji printf). Funkcja printfn dodaje też znak nowego wiersza na końcu wyświetlanego tekstu. Tu wzorzec d to miejsce przeznaczone na liczbę całkowitą, a pozostała część tekstu jest wyświetlana w dosłownej postaci w konsoli. F# obsługuje też powiązane funkcje, na przykład printf, sprintf i fprintf (ich omówienie znajdziesz w rozdziale 4.). Rodzina funkcji printf (inaczej niż w C i C++) formatuje tekst z zachowaniem bezpieczeństwa ze względu na typ. Kompilator języka F# sprawdza, czy kolejne argumenty są zgodne z wymogami poszczególnych miejsc na dane. Przyrostek n w nazwie printfn oznacza, że po danych wyjściowych rozpoczynany jest nowy wiersz. W F# tekst można formatować także w inny sposób. Możesz na przykład bezpośrednio wykorzystać biblioteki platformy .NET: System.Console.WriteLine( -- Liczba s(cid:239)ów w tek(cid:258)cie: {0} , numWords) System.Console.WriteLine( -- Liczba powtórze(cid:241): {0} , numDups) Sekwencja {0} wyznacza miejsce na dane, przy czym kompilator nie sprawdza tu, czy argumenty pasują do tego miejsca. Za pomocą funkcji printfn można też pokazać, jak stosować sekwencyjnie uruchamiane wyrażenia do wywoływania efektów w świecie zewnętrznym. Podobnie jak w wyrażeniach let...in... czasem wygodnie jest zapisywać sekwencyjnie wykonywany kod w jednym wierszu. W tym celu dwa wyrażenia należy rozdzielić średnikiem (;). Pierwsze podwyrażenie jest przetwarzane (zwykle w celu wywołania efektów ubocznych), jego wynik zostaje pominięty, a wartością całego wyrażenia zostaje wynik drugiego podwyrażenia. Oto prostszy przykład zastosowania tego konstruktu: let two = (printfn Witaj, (cid:258)wiecie ; 1 + 1) let four = two + two Ten kod po uruchomieniu wyświetli napis Witaj, (cid:258)wiecie tylko jeden raz — gdy uruchomiona zostanie definicja wartości two. W F# nie występują typowe instrukcje. Fragment (printfn Witaj, (cid:258)wiecie ; 1 + 1) jest wyrażeniem, jednak w trakcie jego przetwarzania pierwsza część powoduje efekt uboczny, po czym wynik tej części jest pomijany. Często wygodnie jest stosować nawiasy do wyodrębniania sekwencyjnie wykonywanego kodu. Kod ze skryptu można (w teorii) umieścić w nawiasie i dodać średnik. Dzięki temu proste konstrukty stosowane w kodzie są lepiej widoczne: (printfn -- Liczba s(cid:239)ów w tek(cid:258)cie: d numWords; printfn -- Liczba powtórze(cid:241): d numDups) (cid:132) Uwaga Symbol ; s(cid:239)u(cid:285)y do zapisywania sekwencyjnie wykonywanego kodu w wyra(cid:285)eniach. Znaki ;; s(cid:200) u(cid:285)ywane do ko(cid:241)czenia interakcji w sesji w narz(cid:218)dziu F# Interactive. (cid:165)redniki s(cid:200) opcjonalne, gdy poszczególne fragmenty sekwencyjnie wykonywanego kodu s(cid:200) umieszczane w odr(cid:218)bnych wierszach rozpoczynaj(cid:200)cych si(cid:218) z tym samym wci(cid:218)ciem. 32 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA U(cid:285)ywanie bibliotek obiektowych w F# Wartość F# wynika nie tylko z tego, co możesz zrobić w samym języku, ale też z komponentów spoza języka, z których można korzystać. Na przykład sam F# nie obejmuje biblioteki do tworzenia graficznego interfejsu użytkownika. Zamiast tego jest powiązany z platformą .NET, a poprzez nią może korzystać z większości znaczących technologii programistycznych dostępnych w popularnych platformach informatycznych. Zetknąłeś się już z jednym przypadkiem zastosowania bibliotek platformy .NET — w pierwszej ze zdefiniowanych wcześniej funkcji: /// Podział łańcucha znaków na słowa w miejscach występowania spacji let splitAtSpaces (text: string) = text.Split | Array.toList Tu text.Split to wywołanie metody instancji Split z biblioteki platformy .NET. Metoda ta jest zdefiniowana dla wszystkich obiektów reprezentujących łańcuchy znaków. Aby lepiej przedstawić tę technikę, w drugim przykładzie wykorzystamy dwie rozbudowane biblioteki dostępne w platformie .NET — System.IO i System.Net. Kompletny przykład pokazany na listingu 2.3 to skrypt, który można uruchomić w narzędziu F# Interactive. Listing 2.3. Używanie w F# bibliotek platformy .NET związanych z sieciami open System.IO open System.Net /// Pobieranie zawartości adresu URL za pomocą żądania sieciowego let http (url: string) = let req = WebRequest.Create(url) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let html = reader.ReadToEnd() resp.Close() html http http://news.bbc.co.uk W tym przykładzie zostało wykorzystanych kilka ważnych bibliotek platformy .NET. Pomaga to zapoznać się z ciekawymi konstruktami języka F#. W następnych punktach opisaliśmy pokazany listing. Dostęp do przestrzeni nazw i modułów za pomocą wywołania open Pierwszy fragment widoczny w tym kodzie to zastosowanie wywołania open do uzyskania dostępu do funkcji z przestrzeni nazw System.IO i System.Net: open System.IO open System.Net Przestrzenie nazw omówiliśmy szczegółowo w rozdziale 7. Pokazane tu deklaracje sprawiają, że można korzystać z dowolnych komponentów dostępnych w wymienionych przestrzeniach nazw bez podawania kompletnych ścieżek. Jeśli nie zastosujesz wywołania open, będziesz musiał posługiwać się podanym poniżej zapisem, którego rozwlekłość jest oczywista: let req = System.Net.WebRequest.Create(url) 33 Poleć książkęKup książkę F# 4.0 DLA ZAAWANSOWANYCH Za pomocą wywołania open można też korzystać z zawartości modułów języka F# bez podawania kompletnych ścieżek. Dokładne omówienie modułów znajdziesz w rozdziale 7. Wi(cid:218)cej o wywo(cid:239)aniu open Wywo(cid:239)anie open to (cid:239)atwy sposób na dost(cid:218)p do zawarto(cid:258)ci przestrzeni nazw i modu(cid:239)ów. Nale(cid:285)y jednak zwróci(cid:202) uwag(cid:218) na pewne szczegó(cid:239)y. Otó(cid:285) wywo(cid:239)anie to nie wczytuje ani nie wskazuje biblioteki. Zamiast tego ujawnia funkcje z ju(cid:285) wczytanych bibliotek. Aby wczyta(cid:202) bibliotek(cid:218), nale(cid:285)y wskaza(cid:202) konkretny plik DLL za pomoc(cid:200) sk(cid:239)adni #r (w skrypcie) lub opcji -r (w wierszu polece(cid:241)). Biblioteki i przestrzenie nazw s(cid:200) niezale(cid:285)ne od siebie. Wiele bibliotek mo(cid:285)e udost(cid:218)pnia(cid:202) funkcje z tej samej przestrzeni nazw, a ka(cid:285)da biblioteka mo(cid:285)e zawiera(cid:202) funkcje z wielu przestrzeni nazw. Cz(cid:218)sto jedna biblioteka obejmuje wi(cid:218)kszo(cid:258)(cid:202) funkcji z danej przestrzeni nazw. Na przyk(cid:239)ad wi(cid:218)kszo(cid:258)(cid:202) funkcji z przestrzeni nazw System.Net znajduje si(cid:218) w bibliotece System.Net.dll, ale niektóre funkcje z tej przestrzeni nazw pochodz(cid:200) z innych bibliotek systemowych. Aby umie(cid:258)ci(cid:202) kod w przestrzeni nazw, dodaj deklaracj(cid:218) namespace w górnej cz(cid:218)(cid:258)ci pliku (opisali(cid:258)my to w rozdziale 7.). Je(cid:258)li dwie przestrzenie nazw obejmuj(cid:200) typy, podrz(cid:218)dne przestrzenie nazw i (lub) modu(cid:239)y o identycznych nazwach, to po u(cid:285)yciu wywo(cid:239)ania open dla tych przestrzeni nazw dost(cid:218)p do ich zawarto(cid:258)ci mo(cid:285)na uzyska(cid:202) za pomoc(cid:200) tych samych skróconych (cid:258)cie(cid:285)ek. Na przyk(cid:239)ad przestrze(cid:241) nazw System obejmuje typ String, a przestrze(cid:241) FSharp.Core zawiera modu(cid:239) String. Wtedy w trakcie wyszukiwania identyfikatora takiego jak String.map sprawdzane s(cid:200) warto(cid:258)ci i sk(cid:239)adowe obu komponentów o nazwie String. Je(cid:258)li pojawia si(cid:218) wieloznaczno(cid:258)(cid:202), wybierany jest element z przestrzeni nazw, dla której open wywo(cid:239)ano pó(cid:283)niej. Je(cid:285)eli zdarzy si(cid:218) kolizja nazw, mo(cid:285)esz zdefiniowa(cid:202) w(cid:239)asne skrócone nazwy modu(cid:239)ów i typów. Oto przyk(cid:239)ady: module MyString = My.Modules.String i type SysString = System.String. Nie mo(cid:285)na jednak tworzy(cid:202) aliasów dla przestrzeni nazw. Pobieranie stron internetowych W drugiej połowie listingu 2.3 używana jest biblioteka System.Net, by zdefiniować funkcję http wczytującą strony internetowe w HTML-u. Aby zbadać działanie tej funkcji, wpisz w narzędziu F# Interactive następujące wiersze: open System.IO;; open System.Net;; let req = WebRequest.Create( http://news.bbc.co.uk );; val req : WebRequest let resp = req.GetResponse();; val resp : WebResponse let stream = resp.GetResponseStream();; val stream : Stream let reader = new StreamReader(stream);; val reader : StreamReader let html = reader.ReadToEnd();; val html : string = html head title BBC News and Sport /title meta http-eq +[959 chars] 34 Poleć książkęKup książkę ROZDZIA(cid:146) 2. (cid:132) PIERWSZY PROGRAM W F# — WPROWADZENIE DO J(cid:125)ZYKA Pierwszy wiersz tego kodu tworzy obiekt typu WebRequest. Używana jest do tego statyczna metoda Create, będąca składową typu System.Net.WebRequest. Wynik tej operacji to obiekt, który działa jak uchwyt przetwarzanego żądania pobrania strony internetowej. Za pomocą tego uchwytu możesz na przykład anulować żądanie lub sprawdzić, czy zostało już przetworzone. Drugi wiersz wywołuje metodę instancji GetResponse. Pozostałe wiersze z przykładu pobierają strumień danych z odpowiedzi na żądanie (służy do tego wywołanie resp.GetResponseStream()), tworzą obiekt służący do odczytu tego strumienia (za pomo
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

F# 4.0 dla zaawansowanych. Wydanie IV
Autor:
, ,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: