Author Archives: juhan

Racket – Espressioni regolari – 1

click

Capitolo nuovo, argomento classico e panicante, RE o regexp, qui, [doc]/guide/regexp.html.

La guida ci ricorda che questa (o meglio lei) è una versione modificata di un classico: Dorai Sitaram, “pregexp: Portable Regular Expressions for Scheme and Common Lisp.” 2002.

A regexp value encapsulates a pattern that is described by a string or byte string. The regexp matcher tries to match this pattern against (a portion of) another string or byte string, which we will call the text string, when you call functions like regexp-match. The text string is treated as raw text, and not as a pattern.

La guida ne parla diffusamente ma se non bastasse: Regular Expressions in The Racket Reference provides more on regexps, qui [doc]/reference/regexp.html.

OK, passo a [doc]/guide/regexp-intro.html dove trovo…

Scrivere regexp

Un paio di cose: userò regexp anch’io e poi il “patterns” del titolo originale –al solito– uhmmm, schemi, modelli, ___________.

A string or byte string can be used directly as a regexp pattern, or it can be prefixed with #rx to form a literal regexp value. For example, #rx"abc" is a string-based regexp value, and #rx#"abc" is a byte string-based regexp value. Alternately, a string or byte string can be prefixed with #px, as in #px"abc", for a slightly extended syntax of patterns within the string.

Most of the characters in a regexp pattern are meant to match occurrences of themselves in the text string. Thus, the pattern #rx"abc" matches a string that contains the characters a, b, and c in succession. Other characters act as metacharacters, and some character sequences act as metasequences. That is, they specify something other than their literal selves. For example, in the pattern #rx"a.c", the characters a and c stand for themselves, but the metacharacter . can match any character. Therefore, the pattern #rx"a.c" matches an a, any character, and c in succession.

Note: When we want a literal \ inside a Racket string or regexp literal, we must escape it so that it shows up in the string at all. Racket strings use \ as the escape character, so we end up with two \s: one Racket-string \ to escape the regexp \, which then escapes the .. Another character that would need escaping inside a Racket string is ".

If we needed to match the character . itself, we can escape it by precede it with a \. The character sequence \. is thus a metasequence, since it doesn’t match itself but rather just .. So, to match a, ., and c in succession, we use the regexp pattern #rx"a\\.c"; the double \ is an artifact of Racket strings, not the regexp pattern itself.

The regexp function takes a string or byte string and produces a regexp value. Use regexp when you construct a pattern to be matched against multiple strings, since a pattern is compiled to a regexp value before it can be used in a match. The pregexp function is like regexp, but using the extended syntax. Regexp values as literals with #rx or #px are compiled once and for all when they are read.

The regexp-quote function takes an arbitrary string and returns a string for a pattern that matches exactly the original string. In particular, characters in the input string that could serve as regexp metacharacters are escaped with a backslash, so that they safely match only themselves.

re0

The regexp-quote function is useful when building a composite regexp from a mix of regexp strings and verbatim strings.

Pausa, argomento nuovo (cioè no ma ogni linguaggio lo tratta a modo suo, piccole (o meno piccole) varianti rispetto alla versione cannica, Stephen Kleene, AWK e Perl).

:mrgreen:

Racket – Input e Output – 3

kepler

Continuando da qui oggi –forse– finisco il capitolo di I/O, qui: [doc]/guide/i_o.html anzi qui: [doc]/guide/serialization.html.

Tipi di dati e serializzazione

Che sarebbe la mia traduzione di Datatypes and Serialization.
prefab structure types (see Prefab Structure Types, [qui: [doc]/guide/define-struct.html)] automatically support serialization: they can be written to an output stream, and a copy can be read back in from an input stream:

io21

Other structure types created by struct, which offer more abstraction than prefab structure types, normally write either using #<....> notation (for opaque structure types) or using #(....) vector notation (for transparent structure types). In neither can the result be read back in as an instance of the structure type:

io22

oops! ma

io23

The serializable-struct form defines a structure type that can be serialized to a value that can be printed using write and restored via read. The serialized result can be deserialized to get back an instance of the original structure type. The serialization form and functions are provided by the racket/serialize library.

io24

In addition to the names bound by struct, serializable-struct binds an identifier with deserialization information, and it automatically provides the deserialization identifier from a module context. This deserialization identifier is accessed reflectively when a value is deserialized.

Uhmmm… da pensarci su un po’.
Intanto passo a [doc]/guide/encodings.html.

bytes, characters e encoding

Functions like read-line, read, display, and write all work in terms of characters (which correspond to Unicode scalar values). Conceptually, they are implemented in terms of read-char and write-char.

More primitively, ports read and write bytes, instead of characters. The functions read-byte and write-byte read and write raw bytes. Other functions, such as read-bytes-line, build on top of byte operations instead of character operations.

In fact, the read-char and write-char functions are conceptually implemented in terms of read-byte and write-byte. When a single byte’s value is less than 128, then it corresponds to an ASCII character. Any other byte is treated as part of a UTF-8 sequence, where UTF-8 is a particular standard way of encoding Unicode scalar values in bytes (which has the nice property that ASCII characters are encoded as themselves). Thus, a single read-char may call read-byte multiple times, and a single write-char may generate multiple output bytes.

The read-char and write-char operations always use a UTF-8 encoding. If you have a text stream that uses a different encoding, or if you want to generate a text stream in a different encoding, use reencode-input-port or reencode-output-port. The reencode-input-port function converts an input stream from an encoding that you specify into a UTF-8 stream; that way, read-char sees UTF-8 encodings, even though the original used a different encoding. Beware, however, that read-byte also sees the re-encoded data, instead of the original byte stream.

OK, infine [doc]/guide/io-patterns.html.

Patterns di I/O

If you want to process individual lines of a file, then you can use for with in-lines:

io25

If you want to determine whether “hello” appears in a file, then you could search separate lines, but it’s even easier to simply apply a regular expression (see Regular Expressions [prossimamente]) to the stream:

io26

If you want to copy one port into another, use copy-port from racket/port, which efficiently transfers large blocks when lots of data is available, but also transfers small blocks immediately if that’s all that is available:

io27

:mrgreen:

Racket – Input e Output – 2

kk0Continuo da qui, oggi qui: [doc]/guide/i_o.html, anzi in dettaglio qui:[doc]/guide/default-ports.html.

Porte di default

For most simple I/O functions, the target port is an optional argument, and the default is the current input port or current output port. Furthermore, error messages are written to the current error port, which is an output port. The current-input-port, current-output-port, and current-error-port functions return the corresponding current ports.

io9

If you start the racket program in a terminal, then the current input, output, and error ports are all connected to the terminal. More generally, they are connected to the OS-level stdin, stdout, and stderr. In this guide, the examples show output written to stdout in purple, and output written to stderr in red italics.

 

io10

OOPS! non vale quanto detto nella guida; non da me. Provato a eseguirla anche come script con lo stesso risultato. Ma who cares? :wink:

The current-port functions are actually parameters, which means that their values can be set with parameterize.

Note: See Dynamic Binding [doc]/guide/parameterize.html: parameterize for an introduction to parameters.

Example: Attenzione!!! con questo esempio (dopo averlo modificato per completarlo) sono riuscito a bloccare il ‘puter in modo assoluto e sono ricorso all’hard reset; rimandato quindi a quando sarò meno niubbo :wink:

(let ([s (open-output-string)])
    (parameterize ([current-error-port s])
      (swing-hammer)
      (swing-hammer)
      (swing-hammer))
    (get-output-string s))

Ma mica finisce qui, anzi passo subito alla pagina successiva: [doc]/guide/read-write.html.

Leggere e scrivere dati

As noted throughout Built-In Datatypes [Racket – tipi di dati built-in – 1], Racket provides three ways to print an instance of a built-in value:

  • print, which prints a value in the same way that is it printed for a REPL result; and
  • write, which prints a value in such a way that read on the output produces the value back; and
  • display, which tends to reduce a value to just its character or byte content—at least for those datatypes that are primarily about characters or bytes, otherwise it falls back to the same output as write.

Here are some examples using each:

io11-17

Overall, print corresponds to the expression layer of Racket syntax, write corresponds to the reader layer, and display roughly corresponds to the character layer.

The printf function supports simple formatting of data and text. In the format string supplied to printf, ~a displays the next argument, ~s writes the next argument, and ~v prints the next argument:

io18

After using write, as opposed to display or print, many forms of data can be read back in using read. The same values printed can also be parsed by read, but the result may have extra quote forms, since a printed form is meant to be read like an expression:

io19

:mrgreen:

Una nota sulla gestione dei files e su Racket tutto

john-belushi-college-obama-posterIl post iniziale sull’I/O mi ha lasciato un qualcosa in sospeso.
Tutto OK, semplice, funziona ma…
Poi ripensandoci mi sono venuti in mente cose che si fanno abitualmente e chissà come si faranno con Racket?
Per esempio appendere testo a un file (p.es. un log) oppure aprire un file in scrittura senza sapere se già ne esiste uno con quel nome o ancora _________. Ecco mille casi. A me queste cose vengono in mente quando sono lontano dal ‘puter, a volte anche in sonno mi sveglio con la fissa “come si fa?”.

E allora per auto-tranquillizzarmi mi dico (si mi parlo da solo, sarà grave?) che appena posso provo, non è il caso di preoccuparsi, mettere il carro davanti ai buoi :roll:

Ecco, adesso che ho riaperto la guida ho la conferma che non era il caso. C’è tutto sulla guida, nel caso in oggetto in File Ports di The Racket Reference, in locale in [doc]/reference/file-ports.html.

In questa pagina vengono descritte (se ho contato bene) dodici procedure, probabilmente più di quelle che servono. E resto tranquillizzato dal verificare –ancore una volta– la completezza e bontà della documentazione di Racket (e famiglia, mica solo lui).

Però…
Ecco adesso devo dire un’altra cosa, su un documento –al solito– molto bene. E speciale, si tratta infatti di The Racket Manifesto.

L’ho letto tutto un paio di volte, non ne ho (ancora) parlato perché un po’ m’intimidisce ma ecco a p.13 si trova:

Racket’s key advantage is its syntax extension system. It makes experienced programmers extremely productive, but it comes with an extraordinarily steep learning curve. Its syntax elaboration algorithm is hard to understand; its toolbox is large and complex; and it has some brittle, unexplored corners that occasionally trip up even experienced programmers. The situation calls for simplifications of the syntax system and for the creation of a smooth ramp for the toolbox (in terms of both tools and documentation).

Ecco. Se non fossi abbastanza incosciente forse mi verrebbe da domandarmi se ce la posso fare. Vero che non ho l’assillo di scadenze (e non mi preoccupano le scarse visite del blog) ma in fondo-in fondo, solo poco-poco ma sì, OK, panico!

alf

D’altro canto: When the going gets tough, the tough get going, come si dice dalle mie parti. E io un po’ a Bluto assomiglio, vero? Altrimenti –se del caso– potrei sempre ripiegare su Alf.

Racket – Input e Output – 1

athena_postage_stamp

Oggi inizio un nuovo capitolo, qui: [doc]/guide/i_o.html.

Input e output

Un po’ di terminologia, sapete ognuno usa la sua e quelli di Racket (tutti über-nerds) ovviamente non fanno eccezione. Continuo a curiosare in PLT e ci sono davvero tante cose, per esempio qui :grin:

A Racket port corresponds to the Unix notion of a stream (not to be confused with racket/stream‘s streams).

A Racket port represents a source or sink of data, such as a file, a terminal, a TCP connection, or an in-memory string. Ports provide sequential access in which data can be read or written a piece of a time, without requiring the data to be consumed or produced all at once. More specifically, an input port represents a source from which a program can read data, and an output port represents a sink to which a program can write data.

Ecco, pronto a passare qui: [doc]/guide/ports.html.

Varietà di porte

Various functions create various kinds of ports. Here are a few examples:

Files: The open-output-file function opens a file for writing, and open-input-file opens a file for reading.

io0

e poi…

io1

If a file exists already, then open-output-file raises an exception by default. Supply an option like #:exists 'truncate or #:exists 'update to re-write or update the file:

io2

Nota: ho aggiunto newline (si poteva usare anche il solito “\n“) perché altrimenti il prompt del terminale è fuori posto :wink:

Instead of having to match open-input-file and open-output-file calls, most Racket programmers will instead use call-with-output-file, which takes a function to call with the output port; when the function returns, the port is closed. Questa è una cosa che viene direttamente dal Lisp, ne avevo parlato dettagliatamente quando studiavo l’ottimo Peter Seibel.

io3

Strings: The open-output-string function creates a port that accumulates data into a string, and get-output-string extracts the accumulated string. The open-input-string function creates a port to read from a string.

io4

TCP Connections: The tcp-connect function creates both an input port and an output port for the client side of a TCP communication. The tcp-listen function creates a server, which accepts connections via tcp-accept.

io5

Process Pipes: The subprocess function runs a new process at the OS level and returns ports that correspond to the subprocess’s stdin, stdout, and stderr. (The first three arguments can be certain kinds of existing ports to connect directly to the subprocess, instead of creating new ports.)

io6

esattamente come

io7

Internal Pipes: The make-pipe function returns two ports that are ends of a pipe. This kind of pipe is internal to Racket, and not related to OS-level pipes for communicating between different processes.

io8

OK, mi piace. Mi viene da fare il paragone con il (vecchio e più macchinoso) I/O del Common Lisp; deve aggiornasi, imho.

:mrgreen:

Ma i giovani conoscono i file di testo?

es0Un post estivo, anche se ormai l’estate sta finendo (cit. per chi se la ricorda). Pare questi post piacciano e allora ecco…

Capitato recentemente. Leggo la bozza quasi definitiva di una tesina (un compito delle vacanze) e prendo appunti. Io che sono vecchio uso un editor normale, Gedit –OK ci sono Emacs e vi ma ormai…– che, ovviamente, produce un file di testo, niente fronzoli tipo font, neretto, sottolineato, corsivo, colori e compagnia bella. Se mi ricordo metto anche l’estensione .txt. E ci sono anche i caratteri accentati, mica solo il set ASCII, tutto l’Unicode.

OK, fatto, salvato, copiato su una chiavetta USB e andato –a piedi, roba di pochi minuti– a casa dello studente.
Qui sono cominciati i fatti che rendono la vita interessante e mi permettono di scrivere questo post. Stavo per dire guai ma sarebbe eccessivo, troppo.
Occorre precisare che il computer del giovane studente (modello, davvero bravo come pochi) ha Windows 8 come sistema operativo. E un antivirus che gode di molta considerazione per via di spiacevoli episodi del recente passato, ma non voglio andare OT.

Il mio file, passato il controllo dell’Ufficio Immigrazione che ha preteso di scannare tutto il driver mobile, è finito, con altri millemila, sul desktop.

Doppio click per aprirlo e –sorpresa– non si vedono gli a-capo. Già Blocco note|Notepad pretende CR-LF invece del solito (per Linux) LF. Che fare?
Ovviamente è da escludere l’installazione di alcunché, anzi il web è considerato pericoloso.
La prima idea è stata quella di visualizzarlo nel browser, c’è Chrome, lo lancio, riduco in finestra e ci droppo sopra il mio file di testo.

browser

L’immagine è dal mio ‘puter, con Firefox, ma è simile a quella di cui sto raccontando.
Uhmmm… gli a-capo ci sono ma i caratteri fuori dal set ASCII non vengono visualizzati correttamente. Sì, si potrebbe dire al browser … ma così al volo, poi va a finire che ci faccio una figura barbina, già vengo visto come lunatico che uso Linux con tutte quelle diavolerie esotiche come i file di testo.

La soluzione, semplice e immediata, è di creare un documento tipo Word –in realtà LibreOffice, ormai usano quello anche loro–, aprirlo e incollarci dentro il testo del file di testo. È un’operazione immediata. Funziona. La dimensione del nuovo documento è di 22.5 kB, contro i 4.9 dell’originale.

doc

Però, questi giovani: sono molto più avanzati di me, sanno messaggiare con lo smartphone componendo i testi (brevi, sintetici) usando con una velocità che implica effetti relativistici i pollici, opponibili, quelli li avrei anch’io ma la sola idea mi spaventa da non dire.

Ma non conoscono gli elementi basilari, come il file di testo. E mettono tutto sul desktop. E usano un sacco sakko di maiuscole. E usano termini come “cartella”, “app”, “scaip”. Tutte cose che non so, a me nessuno dice mai niente :mrgreen:

Visto nel Web – 197

Finita la stagione delle ferie si torna alla solita routine –prossimamente. Intanto ecco cosa ho visto nel Web.

11935576_10206359150371376_2293463242272500239_n

Convert an Android Device to Linux
::: Linux Magazine

Documents Indicate Apple Is Building a Self-Driving Car
::: Slashdot

Mozilla Tests Improved Privacy Mode For Firefox
::: Slashdot

The Promise Of 5G
::: TechCrunch

Kjell – a refurbished Erlang shell with support for color profiles and extensions
::: karlll

IMG_5843

ACM Classic Books Series
intrigante assay; e al solito –OK :wink:
::: Lambda the Ultimate

Facebook Should Pay All of Us
::: The New Yorker

A graphic guide to algorithms
::: dlion92

Overheard at pool just now
::: extempore2

Meet Dash & Dot
Discover a new world of play, learning and adventure.
::: Make Wonder

evolution

Studente di Harvard scopre un difetto di Messenger, Facebook gli revoca lo stage
::: la Stampa

Bash Pitfalls
non nuovo ma …
::: Greg’s Wiki

ShareLaTeX has over 500,000 users!
::: sharelatex

Anti-Science Trolls are Starting Edit Wars on Wikipedia
::: Gizmodo

Rupert Murdoch Won’t Be Teaching Your Children To Code After All
::: Slashdot

Quotation-Steve-Wozniak-life-best-people-Meetville-Quotes-235195

IBM Launches Linux-Only Mainframes
::: Slashdot  ::: Amplify the Signal ::: Ubuntu Insights

State of the Haskell ecosystem – August 2015
::: Gabriel439

Lettera aperta sulla questione Office365 all’assessore alla sanità della Provincia di Bolzano
::: LibreItalia ::: Tech Economy

First feedback on my @university Scala-Java interop class today
::: travisbrown

batman

Comment atteindre Inbox Zero à la rentrée
::: CommitStrip

Using context managers in test setUp
::: Ned Batchelder

Debate Over Amazon Working Conditions Goes Back Years
::: Slashdot

Map of all Public Libraries in the USA
Jake & Python: miracoli resi ordinaria amministrazione
::: jakevdp

At 5,200 comments the Amazon story is now officially the most commented-upon story in NYT history
::: fmanjoo

0e63884d-e06a-4412-bec8-f692f0b409e1

Una storia di giornalismo: New York Times vs. Amazon
::: Giuseppe Granieri ::: Scott Berkun

Here’s what we know about the Ashley Madison hack
::: Fusion ::: Ars Technica ::: mikko ::: mikko ::: fabiochiusi

L’intelligenza artificiale contro il terrore dell’ISIS
::: Oggi Scienza

Intel: il software vocale di Stephen Hawking è ora gratuitamente scaricabile
::: Gravità Zero

Intel Promises ‘Optane’ SSDs Based On Technology Faster Than Flash In 2016
::: Slashdot

Łucja Goliasz

Łucja Goliasz

The Future Of The Web Is All About Context
::: TechCrunch

Facebook overtakes Google as referrer to news sites
::: nxthompson

Getting started with ‘The Little Prover’
sarebbe tutto un mondo nuovo da esplorare; solo che la vita è troppo breve
::: LambdaCat

Chinese police arrest 15,000 for Internet crimes
::: Reuters

Eric Lippert’s Sharp Regrets
conosco chi usa quasi solo C# anche se non ne parlo mai
::: Lambda the Ultimate

CMjouR-W8AANr7H

Smartphone, per innovare è meglio ascoltare i ragazzi
::: Wired

Com’è la sicurezza dei siti scolastici italiani? Imbarazzante
::: Il Disinformatico

For close to 90% of the #world population #LibreOffice is available in the own #language
::: libreoffice

Rural #Brazil will find alternatives to Internet.org
::: webwewant

stitchcounter-scm – Command line tool to help you with knitting and crocheting
It is a porting in Chicken Scheme of the same program I wrote in Clojure and in C
::: manuel-uberti

73153544-1b8e-4a77-a3fa-9c830645b1f9

Installare stampante multifunzione alla sister
per evitare il ritorno alla barbarie
::: dcavedon

Go 1.5 is released
::: The Go Programming Language

I nuovi analfabeti: usano Facebook, ma non sanno interpretare la realtà
::: Wired

Linus Torvalds Isn’t Looking 10 Years Ahead For Linux and That’s OK
concordo perfettamente :wink:
::: Slashdot

11095476_915321581854554_6266519450244667531_n

Une histoire de mot de passe
::: CommitStrip

Tutto l’openness che serve ai bambini in una chiavetta: Freestyle PC for Kids
::: Tech Economy

Ubuntu 15.10 To Ship With Gnome’s Overlay Scrollbars By Default, Ditching Unity’s Overlay Scrollbars
::: Web Upd8

Why Aren’t People Using Smalltalk?
::: Medium

Attacchi informatici in tempo reale
ipnotico
::: SIAMO GEEK

vr

Sergey Brin on Google Lens
::: Google+

L. Peter Deutsch invented the first interactive #Lisp REPL in 1963 when he was 17
::: RainerJoswig

Un obolo per Microsoft
::: Tech Economy

L’ #informatica nei film americani
::: Genjuro75

Annamo bene #Windows10
::: djnooz

Pinuccio

Pinuccio

Google’s feature or (wanted) bug?
::: Google+

Google integrates Twitter into its desktop search results
::: The Next Web

Meet Linux’s Newest File-System: Bcachefs
::: Slashdot

Perché Spotify vuole sapere tutto dei suoi utenti
::: Chiusi nella rete

Guida pratica al software libero… e gratuito
::: Gravità Zero

11873518_745554048904739_2378862926896776826_n

Canonical is letting the Ubuntu Software Center wither and die
::: PCWorld

I love it when I can write a single SQL
::: thomasfuchs

New recipe, HtMaB
::: jasonyeojs

casamonica

Racket – contratti – 11

ssContinuando da qui dovrei descrivere (o copiare) l’esempio che trovo qui: [doc]/guide/contracts-examples.html.

Un esempio completo

Ho un problema, grosso. Ci ho provato ma non sono riuscito a aggiungere niente di mio. L’esercizio è fattibile, chiaro ma conviene davvero vederlo di là.
Passo quindi al capitolo successivo, [doc]/guide/contracts-gotchas.html, i gotchas dei contratti. Uh! chissà come devo tradurre gotcha?

Contratti e eq?

As a general rule, adding a contract to a program should either leave the behavior of the program unchanged, or should signal a contract violation. And this is almost true for Racket contracts, with one exception: eq?.

The eq? procedure is designed to be fast and does not provide much in the way of guarantees, except that if it returns true, it means that the two values behave identically in all respects. Internally, this is implemented as pointer equality at a low-level so it exposes information about how Racket is implemented (and how contracts are implemented).

Contracts interact poorly with eq? because function contract checking is implemented internally as wrapper functions. For example, consider this module:

#lang racket
 
(define (make-adder x)
  (if (= 1 x)
      add1
      (lambda (y) (+ x y))))
(provide (contract-out
          [make-adder (-> number? (-> number? number?))]))

It exports the make-adder function that is the usual curried addition function, except that it returns Racket’s add1 when its input is 1.

You might expect that

(eq? (make-adder 1)
     (make-adder 1))

would return #t, but it does not. If the contract were changed to any/c (or even (-> number? any/c)), then the eq? call would return #t.

Moral: Do not use eq? on values that have contracts.

Confini di contratto e define/contract

The contract boundaries established by define/contract, which creates a nested contract boundary, are sometimes unintuitive. This is especially true when multiple functions or other values with contracts interact. For example, consider these two interacting functions:

c11

One might expect that the function g will be blamed for breaking the terms of its contract with f. Blaming g would be right if f and g were directly establishing contracts with each other. They aren’t, however. Instead, the access between f and g is mediated through the top-level of the enclosing module.

More precisely, f and the top-level of the module have the (-> integer? integer?) contract mediating their interaction; g and the top-level have (-> string?) mediating their interaction, but there is no contract directly between f and g. This means that the reference to f in the body of g is really the top-level of the module’s responsibility, not g‘s. In other words, the function f has been given to g with no contract between g and the top-level and thus the top-level is blamed.

If we wanted to add a contract between g and the top-level, we can use define/contract‘s #:freevar declaration and see the expected blame:

c12

Moral: if two values with contracts should interact, put them in separate modules with contracts at the module boundary or use #:freevar.

Contratti con #:exists e predicati

Much like the eq? example above, #:∃ contracts can change the behavior of a program.

Specifically, the null? predicate (and many other predicates) return #f for #:∃ contracts, and changing one of those contracts to any/c means that null? might now return #t instead, resulting in arbitrarily different behavior depending on how this boolean might flow around in the program.

To work around the above problem, the racket/exists library behaves just like racket, but predicates signal errors when given #:∃ contracts.

Moral: Do not use predicates on #:∃ contracts, but if you’re not sure, use racket/exists to be safe.

Definire contratti ricorsivi

When defining a self-referential contract, it is natural to use define. For example, one might try to write a contract on streams like this:

c13

Unfortunately, this does not work because the value of stream/c is needed before it is defined. Put another way, all of the combinators evaluate their arguments eagerly, even though the values that they accept do not.

Instead, use

c14

The use of recursive-contract delays the evaluation of the identifier stream/c until after the contract is first checked, long enough to ensure that stream/c is defined.

See also Checking Properties of Data Structures [Controllare le proprietà di strutture di dati].

Mescolare set! e contract-out

The contract library assumes that variables exported via contract-out are not assigned to, but does not enforce it. Accordingly, if you try to set! those variables, you may be surprised. Consider the following example:

c15

Both calls to print-latest print 0, even though the value of x has been incremented (and the change is visible inside the module x).

To work around this, export accessor functions, rather than exporting the variable directly, like this:

#lang racket
 
(define (get-x) x)
(define (inc-x!) (set! x (+ x 1)))
(define x 0)
(provide (contract-out [inc-x! (-> void?)]
                       [get-x (-> integer?)]))

Moral: This is a bug that we will address in a future release.

Basta con i contratti, prossimamente si cambia :mrgreen:

Racket – contratti – 10

pogo0

Sempre sui contratti, qui: [doc]/guide/contracts-general-functions.html, anzi qui: [doc]/guide/contracts-exists.html, continuando a copiare da qui.

Contratti astratti usando #:exists e #:∃

The contract system provides existential contracts that can protect abstractions, ensuring that clients of your module cannot depend on the precise representation choices you make for your data structures.

Note: You can type #:exists instead of #:∃ if you cannot easily type Unicode characters; in DrRacket, typing \exists followed by either alt-\ or control-\ (depending on your platform) will produce .
Uhmmm… con la tastiera italiana non funziona. E se proprio si vuole utilizzare si può ricorrere al solito metodo (con Linux) per i caratteri Unicode Shift-Ctrl-u e poi il codice che per exists è 2203, mentre per λ è 03bb. Inoltre con Ctrl-\ si ottiene λ in DrRacket.

The contract-out form allows you to write

#:∃ name-of-a-new-contract

as one of its clauses. This declaration introduces the variable name-of-a-new-contract, binding it to a new contract that hides information about the values it protects.

As an example, consider this (simple) implementation of a queue datastructure:

c9

This code implements a queue purely in terms of lists, meaning that clients of this data structure might use car and cdr directly on the data structure (perhaps accidentally) and thus any change in the representation (say to a more efficient representation that supports amortized constant time enqueue and dequeue operations) might break client code.

To ensure that the queue representation is abstract, we can use #:∃ in the contract-out expression, like this:

c10

Now, if clients of the data structure try to use car and cdr, they receive an error, rather than mucking about with the internals of the queues.

:roll:

Ah, vedere anche quello che seguirà prossimamente :mrgreen:

Racket – contratti – 9

fw

Oggi qui: [doc]/guide/contracts-general-functions.html, in particolare qui: [doc]/guide/contracts-struct.html continuando a raccontare (e copiare) da qui.

Contratti nelle strutture

Modules deal with structures in two ways. First they export struct definitions, i.e., the ability to create structs of a certain kind, to access their fields, to modify them, and to distinguish structs of this kind against every other kind of value in the world. Second, on occasion a module exports a specific struct and wishes to promise that its fields contain values of a certain kind. This section explains how to protect structs with contracts for both uses.

c8

Garanzie per un valore specifico

If your module defines a variable to be a structure, then you can specify the structure’s shape using struct/c:

#lang racket
(require lang/posn)
 
(define origin (make-posn 0 0))
 
(provide (contract-out
          [origin (struct/c posn zero? zero?)]))

In this example, the module imports a library for representing positions, which exports a posn structure. One of the posns it creates and exports stands for the origin, i.e., (0,0), of the grid.

Note: See also vector/c and similar contract combinators for (flat) compound data. Proprio come dicevo io :wink:

Garanzie per tutti i valori

How to Design Programs teaches that posns should contain only numbers in their two fields. With contracts we would enforce this informal data definition as follows:

#lang racket
(struct posn (x y))
 
(provide (contract-out
          [struct posn ((x number?) (y number?))]
          [p-okay posn?]
          [p-sick posn?]))
 
(define p-okay (posn 10 20))
(define p-sick (posn 'a 'b))

This module exports the entire structure definition: posn, posn?, posn-x, posn-y, set-posn-x!, and set-posn-y!. Each function enforces or promises that the two fields of a posn structure are numbers — when the values flow across the module boundary. Thus, if a client calls posn on 10 and 'a, the contract system signals a contract violation.

The creation of p-sick inside of the posn module, however, does not violate the contracts. The function posn is used internally, so 'a and 'b don’t cross the module boundary. Similarly, when p-sick crosses the boundary of posn, the contract promises a posn? and nothing else. In particular, this check does not require that the fields of p-sick are numbers.

The association of contract checking with module boundaries implies that p-okay and p-sick look alike from a client’s perspective until the client extracts the pieces:

#lang racket
(require lang/posn)
 
... (posn-x p-sick) ...

Using posn-x is the only way the client can find out what a posn contains in the x field. The application of posn-x sends p-sick back into the posn module and the result value – 'a here – back to the client, again across the module boundary. At this very point, the contract system discovers that a promise is broken. Specifically, posn-x doesn’t return a number but a symbol and is therefore blamed.

This specific example shows that the explanation for a contract violation doesn’t always pinpoint the source of the error. The good news is that the error is located in the posn module. The bad news is that the explanation is misleading. Although it is true that posn-x produced a symbol instead of a number, it is the fault of the programmer who created a posn from symbols, i.e., the programmer who added

(define p-sick (posn 'a 'b))

to the module. So, when you are looking for bugs based on contract violations, keep this example in mind.

If we want to fix the contract for p-sick so that the error is caught when sick is exported, a single change suffices:

(provide
 (contract-out
  ...
  [p-sick (struct/c posn number? number?)]))

That is, instead of exporting p-sick as a plain posn?, we use a struct/c contract to enforce constraints on its components.

Controllare le proprietà di strutture di dati

Contracts written using struct/c immediately check the fields of the data structure, but sometimes this can have disastrous effects on the performance of a program that does not, itself, inspect the entire data structure.

As an example, consider the binary search tree search algorithm. A binary search tree is like a binary tree, except that the numbers are organized in the tree to make searching the tree fast. In particular, for each interior node in the tree, all of the numbers in the left subtree are smaller than the number in the node, and all of the numbers in the right subtree are larger than the number in the node.

We can implement a search function in? that takes advantage of the structure of the binary search tree.

#lang racket
 
(struct node (val left right))
 
; determines if `n' is in the binary search tree `b',
; exploiting the binary search tree invariant
(define (in? n b)
  (cond
    [(null? b) #f]
    [else (cond
            [(= n (node-val b))
             #t]
            [( n (node-val b))
             (in? n (node-right b))])]))
 
; a predicate that identifies binary search trees
(define (bst-between? b low high)
  (or (null? b)
      (and ( . boolean?)]
          [in? (number? bst? . -> . boolean?)]))

In a full binary search tree, this means that the in? function only has to explore a logarithmic number of nodes.

The contract on in? guarantees that its input is a binary search tree. But a little careful thought reveals that this contract defeats the purpose of the binary search tree algorithm. In particular, consider the inner cond in the in? function. This is where the in? function gets its speed: it avoids searching an entire subtree at each recursive call. Now compare that to the bst-between? function. In the case that it returns #t, it traverses the entire tree, meaning that the speedup of in? is lost.

In order to fix that, we can employ a new strategy for checking the binary search tree contract. In particular, if we only checked the contract on the nodes that in? looks at, we can still guarantee that the tree is at least partially well-formed, but without changing the complexity.

To do that, we need to use struct/dc to define bst-between?. Like struct/c, struct/dc defines a contract for a structure. Unlike struct/c, it allows fields to be marked as lazy, so that the contracts are only checked when the matching selector is called. Also, it does not allow mutable fields to be marked as lazy.

The struct/dc form accepts a contract for each field of the struct and returns a contract on the struct. More interestingly, struct/dc allows us to write dependent contracts, i.e., contracts where some of the contracts on the fields depend on the values of other fields. We can use this to define the binary search tree contract:

#lang racket
 
(struct node (val left right))
 
; determines if `n' is in the binary search tree `b'
(define (in? n b) ... as before ...)
 
; bst-between : number number -> contract
; builds a contract for binary search trees
; whose values are between low and high
(define (bst-between/c low high)
  (or/c null?
        (struct/dc node [val (between/c low high)]
                        [left (val) #:lazy (bst-between/c low val)]
                        [right (val) #:lazy (bst-between/c val high)])))
 
(define bst/c (bst-between/c -inf.0 +inf.0))
 
(provide (struct-out node))
(provide (contract-out
          [bst/c contract?]
          [in? (number? bst/c . -> . boolean?)]))

In general, each use of struct/dc must name the fields and then specify contracts for each field. In the above, the val field is a contract that accepts values between low and high. The left and right fields are dependent on the value of the val field, indicated by their second sub-expressions. They are also marked with the #:lazy keyword to indicate that they should be checked only when the appropriate accessor is called on the struct instance. Their contracts are built by recursive calls to the bst-between/c function. Taken together, this contract ensures the same thing that the bst-between? function checked in the original example, but here the checking only happens as in? explores the tree.

Although this contract improves the performance of in?, restoring it to the logarithmic behavior that the contract-less version had, it is still imposes a fairly large constant overhead. So, the contract library also provides define-opt/c that brings down that constant factor by optimizing its body. Its shape is just like the define above. It expects its body to be a contract and then optimizes that contract.

(define-opt/c (bst-between/c low high)
  (or/c null?
        (struct/dc node [val (between/c low high)]
                        [left (val) #:lazy (bst-between/c low val)]
                        [right (val) #:lazy (bst-between/c val high)])))

:evil: Già detto panico? altrimenti panico! :evil:
Però –ora che ci penso– questo è già fatto, e si capisce, è OK. Basta sapere che c’è — e qui entra in campo la documentazione (ottima) :grin:

:mrgreen:

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 88 follower