10 settembre, 2019

Visibilità (scope) lessicale e dinamica - 1

Carlo Nardone 30-4-19

Primo post di almeno un paio su un argomento che m'intriga e che recentemente mi ha creato qualche problema nel tradurre un algoritmo da un linguaggio a un altro. Sì mai tradurre. A proposito non so se la traduzione di scope in visibilità sia corretta; i francesi usano portée che però sarebbe sbagliato tradurre con portata: mai tradurre.

Conto di distribuire le mie pensate in più puntate perché mi sto ancora documentando e non so se le mie conclusioni sono sensate. Per intanto comincio con l'esame del post di Ming-Ho Yee che ha scatenato tutto: Lexical and Dynamic Scope.

Ming-Ho mi devi già qualche ora di sonno ma ti sono grato per il tuo post. Grazie e perdona se copio.

Non riassumo il post, è da leggere. Racconto invece cosa ho fatto (non è che l'inizio): ho implementato nei linguaggi di scripting che uso normalmente il suo esempio in pseudocode, questo:


Python

#!/usr/bin/python3

x = 1
def f(a): return x + a
def g():
    x = 2
    return f(0)
print(g())

ed ecco:

$ py3 ld.py
1
$

JavaScript

#!/usr/bin/node

var x = 1
function f(a) {
    return x + a
    }
function g() {
    x = 2
    return f(0)
}
console.log(g())

che produce

$ node ld.js
2
$

però sono stato troppo precipitoso, ho tradotto in automatico, senza pensarci su, ora che ci penso l'istruzione 4 di Ming-Ho è da intendersi interna alla funzione g() e quindi correggo così:

#!/usr/bin/node

var x = 1
function f(a) {
    return x + a
    }
function g() {
    var x = 2  // <- modifica qui
    return f(0)
}
console.log(g())

e allora:

$ node ldv.js
1
$

Racket

PRL è un sito strettamente legato a Racket, linguaggio del quale sono perdutamente innamorato; non lo uso correntemente per gli script (ma a pensarci anche JS solo quando costretto) ma non posso non invocarlo:

#!//usr/bin/racket

#lang racket

(define x 1)
(define (f a) (+ x a))
(define (g)
  (define x 2)
  (f 0))
(println (g))

$ rkt ld.rkt
1
$

(chiedo di sospendere il giudizio riguardo all'istruzione 4 già precedente citata, a breve mi spiego).

Bash

No, Bash non lo uso per cose come questa ma mi serve, anche per come lo cita Ming-Ho.

#!/bin/bash

x=1
function f () {
    echo $(( $x + $a ))
}
function g () {
    x=2
    echo $(f)
}
a=0
echo $(g)

eseguo e ottengo:

$ bash ld.sh
2
$

OK 🙂 A questo punto dovrebbe essere chiaro anche a quelli come me che la funzione f() usa il valore di x che vede ed essendo globale vede la definizione in riga 1 di del codice di Ming-Ho. Tranne in Bash, dove tutte le variabili sono globali e nella versione veloce JS. Questa particolarità di JS davvero non mi piace, o sono solo io che dimentico spesso var?

Ovviamente credo di dover produrre le versioni con l'istruzione 4 globale nei due linguaggi usati.

Python

#!/usr/bin/python3

x = 1
def f(a): return x + a
def g():
    global x # <- instruzione aggiunta
    x = 2
    return f(0)
print(g())

ottengo

$ py3 ldg.py
2
$

Racket

#!//usr/bin/racket

#lang racket

(define x 1)
(define (f a) (+ x a))
(define (g)
  (set! x 2) ;; <- modifica qui
  (f 0))
(println (g))

ed ecco

$ rkt ldg.rkt
2
$

OK? 💥👌🤩
(continua, probabilmente, forse) 🙂
🔴

Nessun commento:

Posta un commento