Alessio Biancalana Grab The Blaster di Alessio Biancalana

MacBook con USB-C, morta-C-tua 🔪

iPhone attacco caricabatteria

Da qualche mese mi è arrivato il computer aziendale nuovo. Voi mi direte, beh, che novità è mai questa? E invece io vi dirò che non solo è un evento non banale perché mica è così scontato che un’azienda dia ai dipendenti l’equipaggiamento, ma tutto questo è ancora più pregno di significato perché il mio laptop aziendale è un MacBook Pro di nuova generazione (per intenderci, quelli colorati Space Gray). Oltre al colore bellissimo e a tutte le considerazioni estetiche che possiamo fare in libertà, questo MacBook mi ha permesso di provare su strada la scelta di Apple di sostituire l’attacco MagSafe con uno slot USB Type-C a cui ovviamente è associato un nuovo tipo di caricabatteria.

Qualche settimana fa dall’alto del mio metro e settanta quasi metro e ottanta mi sono guardato (lo so che non si dice) il mio laptop e il mio caricabatteria e ho deciso di stilare una lista dei pregi e dei difetti di questo nuovo caricabatteria USB-C.

Questi i pregi:

  • È comodo avere un caricabatteria USB-C in più. Avendo anche uno smartphone Android con attacco USB-C (il mio caro Nexus 6P), posso ricaricarci sia il computer che il cellulare.

E basta.

Veniamo ai difetti:

  • Ancora un altro tipo di alimentatore? Ormai comincio a credere che Apple abbia una politica di obsolescenza programmata specifica per gli alimentatori, una cosa sadica per cui se ti si rompe l’alimentatore del tuo MacBook di quasi dieci anni fa ormai sei nelle piste e ti conviene votarti a Satana (o Santana, dipende se hai bisogno anche di un assolo) e prostituirti per comprare direttamente un portatile nuovo1. Perché ricordiamo che nei vecchi MacBook c’era un MagSafe, che è stato poi cambiato in favore di un altro attacco. E ora abbiamo questo bellissimo connettore USB-C, così diverso da quello che c’era prima che viene quasi da chiedere ad Apple se si sta divertendo.
  • Non vorrei mai inciampare in un cavo teso attaccato al mio nuovo MacBook – perché mentre con i modelli precedenti ho sempre potuto fare il casino che volevo, tanto l’alimentatore in caso di inciampo si staccava da solo preservando il portatile da cadute fortunosamente accidentali e il sottoscritto da bestemmie assolutamente intenzionali, con questo mi porto appresso tutto, e le profanità che prima erano solo paventate hanno una probabilità elevatissima di tramutarsi in realtà.
  • Ammazza che mazza! I cavi USB-C sono mastodontici in spessore rispetto a quelli usati nei MagSafe, il che significa che mentre prima potevamo flettere il nostro cavo di alimentazione (con i rischi che ne derivavano), in questa veste abbiamo un cavo assolutamente più rigido e “importante” come dimensioni. Non è niente di che, ma giacché siamo lamentosi tutto fa brodo.
  • Come corollario del punto precedente abbiamo questo: avete presente le bellissime e piccolissime staffe a L che uscivano dal caricabatteria e ci permettevano di arrotolare il cavo? Una trovata di design eccezionale, secondo me, che con questo modello è andata a farsi benedire. Le staffe sono state eliminate, costringendoci a piegare nei modi più fantasiosi il cavo che è troppo spesso per essere arrotolato in quel modo.
  • In coda a tutto questo, un difetto fondamentale: se voglio caricare il computer e attaccare un paio di monitor esterni o qualche altro tipo di periferica2 sono condannato a comprare uno di quegli adattatori maledetti che infatti sono stato costretto a prendere, perché è letteralmente impossibile pensare di usare un computer con questa concezione alle spalle senza un adattatore che ci aiuti a rendere compatibile tutto quello che abbiamo avuto finora con un futuro dove tutto quello che abbiamo costruito è diventato obsoleto in nome di una miniaturizzazione che onestamente lascia il tempo che trova. Ma questa sono convinto che sia una storia da raccontare un’altra volta3, come scrisse Michael Ende.

Ti stai solo lamentando

Certo. È vero. Ed è anche vero che in realtà ci sono delle cose positive di Apple che adotta l’USB-C insieme ad altri produttori. Io però sono convinto che questi tratti positivi non siano per niente inerenti l’esperienza utente, che viene solo martirizzata in nome di un ideale di innovazione che finora ha prodotto solo mostri. Allo stesso tempo, guardo gli altri produttori e mi chiedo se veramente quello che abbiamo intenzione di fare è spingerci così tanto a comprare attrezzi che hanno così disperatamente bisogno di altri attrezzi non appena usciti dalla scatola – attrezzi che non abbiamo, e che siamo condannati a comprare subito pena non poter usare più niente del nostro “vecchio repertorio” di penne USB e cavi di rete (per dire).

Apple pensa solo al futuro? Può essere, ma io per trasferire un film da computer all’altro ho dovuto aspettare due giorni per rientrare in possesso del mio adattatore. E questo è il presente.

  1. Prima che qualcuno di voi sapientoni me lo dica nei commenti, io lo so che alimentatori anche di vecchia generazione si comprano sull’Apple Store online. Ma a parte costare un botto, ho sempre il timore ancestrale di scontrarmi con quello che ogni nerd teme e che infesta ogni suo incubo: l’esaurimento scorte quando hai bisogno di un ricambio. 

  2. Periferica, che termine vecchio. Però mi rievoca bei ricordi, ricordi di un’informatica che a conti fatti non esiste quasi più. 

  3. Volete uno spoiler? Ho ancora il mio vecchio MacBook, continuo a usarlo come laptop personale ed è il computer (specie in questo periodo) tra i miei che uso di più. 

Elixir per idioti /6, sua maestà il pattern matching

Visto che nell’ultimo episodio abbiamo parlato di pipe operator, con cui cominciamo ad affrontare sul serio l’espressività di un linguaggio funzionale, andiamo a parare sull’ultimo ostacolo che ci separa dall’avere ogni base per cominciare a praticare il nostro Elixir-jutsu in maniera efficace. Sto parlando della feature che ogni linguaggio funzionale porta con sé, da Erlang a Scala al nostro Elixir, ovvero il pattern matching.

È più facile a farsi che a dirsi (o spiegarsi), ma ci proverò lo stesso con qualche parola astrusa: Elixir possiede la capacità di lasciarci definire più “clause”, ovvero funzioni o altri tipi di espressioni, per poi decidere lui stesso quale definizione tra quelle che abbiamo scritto si applica in maniera più vicina all’input che viene dall’esterno. Ripeto: possiamo definire più casi in base a molteplici input, e il runtime provvede ad identificare la forma più vicina di volta in volta all’input fornito per poi comportarsi di conseguenza. Ma a questo punto facciamo prima a vedere un esempio pratico. Un modulo può avere più di una definizione della stessa funzione in base all’input:

iex(1)> defmodule SalutePeople do
...(1)>   def hello("Alessio") do
...(1)>     IO.puts("Hello Alessio")
...(1)>   end
...(1)>
...(1)>   def hello("Agnese") do
...(1)>     IO.puts("Hello my love")
...(1)>   end
...(1)>
...(1)>   def hello(_anyone) do
...(1)>     IO.puts("Who the fuck are you?")
...(1)>   end
...(1)> end
{:module, SalutePeople,
 <<70, 79, 82, 49, 0, 0, 5, 28, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 147,
   0, 0, 0, 15, 19, 69, 108, 105, 120, 105, 114, 46, 83, 97, 108, 117, 116, 101,
   80, 101, 111, 112, 108, 101, 8, 95, 95, ...>>, {:hello, 1}}

Definendo un modulo così, cosa otteniamo? Otteniamo una funzione hello che si comporta diversamente di fronte a me, alla mia ragazza, o davanti a chiunque altro.

iex(2)> SalutePeople.hello("Alessio")
Hello Alessio
:ok
iex(3)> SalutePeople.hello("Agnese")
Hello my love
:ok
iex(4)> SalutePeople.hello("Chiunque altro")
Who the fuck are you?
:ok
iex(5)>

Il pattern matching ci permette di specificare in maniera performante ed efficace come i nostri programmi si devono comportare in base a diversi input. Possiamo usare questa caratteristica non solo nelle firme delle funzioni (le firme sono quella sintassi def tiziocaio(argomento) do ... end) ma anche nei nostri case statement. Normalmente, in linguaggi come JavaScript o Ruby, gli swith case non sono altro che delle maniere leggermente più tollerabili (e dipende anche dai casi) di scrivere una scala a pioli di if else. Nei linguaggi come Elixir abbiamo il pattern matching come arma definitiva per renderli molto più potenti. Prendo il primo esempio che mi capita a tiro dal manuale di Elixir:

iex> case {1, 2, 3} do
...>   {4, 5, 6} ->
...>     "This clause won't match"
...>   {1, x, 3} ->
...>     "This clause will match and bind x to 2 in this clause"
...>   _ ->
...>     "This clause would match any value"
...> end
"This clause will match and bind x to 2 in this clause"

In pratica rispetto a differenti pattern, il runtime come abbiamo già detto è in grado di riconoscere quello che si avvicina di più al caso corrente. In caso di mancato riconoscimento di un pattern, viene applicata la soluzione più generica, che in un case statement viene indicata con l’underscore come possiamo vedere dall’esempio.

Vai alla parte 5

Paura e delirio nel mondo delle telco, ma WindTre resta calma

WindTre resta ferma sul suo posizionamento mentre Vodafone sforna Ho e TIM sforna KENA Mobile

L’arrivo di Iliad all’interno dell’ecosistema formato dalle telco italiane è stato un piccolo sconvolgimento. Non siamo nuovi a tariffe al ribasso e slogan “da acchiappo”, ma l’arrivo di un nuovo operatore è sempre rivestito da un’aura di mistero, hype, e quando poi il velo di Maya si rompe c’è lo scompiglio.

In risposta all’arrivo di Iliad:

  • Vodafone ha lanciato il suo nuovo brand Ho;
  • TIM ha lanciato il nuovo operatore KENA;
  • WindTre, viceversa, dimostra l’atteggiamento opposto proseguendo il suo percorso senza lanciare nulla di nuovo.

A questo proposito, ci sono una serie di considerazioni da fare: la prima è puramente commerciale, ovvero che una volta superata l’iniziale fascinazione per un nuovo brand più fresco, mi chiedo cosa potrebbe pensare un consumatore di aziende che non fanno altro che inseguire, sfornando qualcosa di nuovo solo perché un altro player ha affrontato il mercato in maniera più aggressiva. La seconda è che “brand nuovo, ma anche no”: un sito fatto in maniera diversa, dei caratteri più arrotondati e delle tariffe da acchiappo non significano necessariamente un rinnovamento infrastrutturale anzi. E cosa ottengono in più i clienti che rimangono con il brand principale anziché affidarsi al nuovo brand che costa meno? Che penalità hanno i clienti di questi nuovi operatori che poi tanto nuovi non sono? Quello che emerge guardando il mercato è solo tanta confusione indotta dalla moltiplicazione di pani, pesci, operatori di telefonia mobile e schede SIM in casa della gente.

In questo panorama va a configurarsi in maniera totalmente diversa WindTre, che non approfitta della confusione del momento per offrire al consumatore qualcosa di nebuloso e confusionario, anzi: attraverso i due storici marchi, Wind e 3 propone ai suoi clienti un’offerta chiara in mezzo al marasma di “nuovi” brand. Sembra quasi una strategia: ricambiare il consumatore con trasparenza e sincerità nelle offerte contrattuali comportandosi con costanza, mentre tutti gli altri cercano solo di fare il verso all’ultimo arrivato producendo una bagarre incredibile. Anche perché poi chi va a perderci, in un modo o nell’altro, è proprio il frastornato cliente.

Elixir per idioti /5, pipe operator e pipeline di funzioni

Quando ho approcciato Elixir per la prima volta, una tra le cose più complicate con cui ho avuto a che fare è stata proprio l’abituarmi a leggere il codice di altri e a capire alcune particolarità del linguaggio, una su tutte il pipe operator. Ve l’ho mostrato nello scorso episodio: il pipe operator (|>) è un operatore particolare che permette di passare l’output di una funzione direttamente alla funzione successiva come primo argomento.

Questo significa che noi possiamo scrivere qualcosa di questo tipo:

IO.puts(divide_by_two(square(10)))

In una forma migliore, che è questa:

10 |> square() |> divide_by_two() |> IO.puts()

E possiamo anche formattarlo perché sia più ordinato:

10
|> square()
|> divide_by_two()
|> IO.puts()

Il funzionamento del pipe operator è abbastanza semplice, si tratta solo di prenderci la mano e di cominciare a “pensare per pipeline”, ovvero immaginare il proprio codice come una sequenza di funzioni per cui l’argomento iniziale che noi forniamo passa attraverso, esattamente come una catena di montaggio, e viene di volta in volta “evoluto” in qualcos’altro.

Personalmente questo concetto di pipeline è qualcosa che mi piace molto, perché permette di architettare il codice in maniera migliore e soprattutto di giocare alle scatole cinesi, per cui una funzione può semplicemente assumere la forma di una grossissima catena di montaggio:

def huge_pipeline(number) do
  number
  |> some_function()
  |> some_other_function()
  |> wow()
  |> such()
  |> code()
end

Ogni funzione di quelle che abbiamo indicato applicherà le sue modifiche al numero in entrata e l’output come abbiamo detto verrà passato alla successiva. Facile no? Proviamo a definire qualche funzione e a giocare col pipe operator per capire meglio.

iex(1)> defmodule SimpleMath do
...(1)>   def square(number), do: number*number
...(1)>   def divide_by_two(number), do: number/2
...(1)> end
{:module, SimpleMath,
 <<70, 79, 82, 49, 0, 0, 4, 196, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 147,
   0, 0, 0, 15, 17, 69, 108, 105, 120, 105, 114, 46, 83, 105, 109, 112, 108,
   101, 77, 97, 116, 104, 8, 95, 95, 105, 110, ...>>, {:divide_by_two, 1}}
iex(2)> SimpleMath.square(2)
4
iex(3)> defmodule HugeModule do
...(3)>   def great_function(number) do
...(3)>     number
...(3)>     |> SimpleMath.square()
...(3)>     |> SimpleMath.divide_by_two()
...(3)>   end
...(3)> end
{:module, HugeModule,
 <<70, 79, 82, 49, 0, 0, 4, 152, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 178,
   0, 0, 0, 16, 17, 69, 108, 105, 120, 105, 114, 46, 72, 117, 103, 101, 77, 111,
   100, 117, 108, 101, 8, 95, 95, 105, 110, ...>>, {:great_function, 1}}
iex(4)> HugeModule.great_function(5)
12.5
iex(5)> HugeModule.great_function(20)
200.0
iex(6)>

Ok, ce l’ho fatta. Giuro che non sto barando, ho scritto ‘sto polpettone nella shell di Elixir, iex, di cui vi ho già parlato.

Quello che ho appena fatto è molto semplice ma secondo me fa capire bene cosa abbiamo davanti: ho scritto un modulo SimpleMath simile a quello dell’episodio precedente, dopodiché in un altro modulo (per comodità) ho riusato queste funzioni definite precedentemente orchestrando una pipeline composta da queste due procedure e il classico valore in input.

Ci siamo. Se avete afferrato come funziona il pipe operator, siete pronti per la prossima grande avventura, ovvero il pattern matching.

Vai alla parte 4

Vai alla parte 6

Elixir per idioti /4, definire moduli e funzioni

La scorsa volta, che ormai è stata un po’ di tempo fa, avevamo visto come operare sulle liste tramite le funzioni messe a disposizione dal modulo Enum. Un modulo non è altro che una raccolta di funzioni, come una scatola degli attrezzi; possiamo usare i moduli per organizzare meglio il nostro codice e raggruppare le funzioni che scriviamo per affinità. Adesso riprendiamo le basi del linguaggio e poniamoci una domanda: cosa succederebbe se io volessi scrivere un modulo tutto mio con blackjack e squillo di lusso in cui raggruppare le mie funzioni?

È abbastanza semplice, ci basta usare defmodule. Un modulo Elixir ha questa faccia:

defmodule Hello do
  def salute(name) do
    IO.puts("I salute you, " <> name)
  end

  def sayhello(name) do
    IO.puts("Hello, " <> name)
  end
end

Insieme a defmodule stiamo imparando anche come definire delle funzioni. Una funzione in Elixir si compone della keyword def, un nome, e degli argomenti (quelli passati tra parentesi). In seguito possiamo richiamare le funzioni del modulo che abbiamo definito in questo modo:

Hello.salute("Alessio")

E otterremo che venga stampato a schermo un saluto col nostro nome, come da codice. Se vogliamo provare a giocare un po’ con la definizione dei moduli possiamo buttare giù uno script Elixir al volo, creando un file chiamato hello.exs con questo contenuto:

defmodule Hello do
  def salute(name) do
    IO.puts("I salute you, #{name}")
  end

  def sayhello(name) do
    IO.puts("Hello, #{name}")
  end
end

Hello.salute("Alessio")
Hello.sayhello("Arcibaldo")

Per eseguirlo ci basta spostarci nella directory dove si trova e lanciarlo con il comando elixir:

$ elixir hello.exs
I salute you, Alessio
Hello, Arcibaldo

Possiamo definire quanti moduli vogliamo. In uno script piccolo di un solo file fatichiamo a vedere l’utilità di una cosa simile, ma quando abbiamo tanti file e un progetto che comincia ad assumere una stazza importante, l’ordine è fondamentale. Per quanto riguarda la creazione di un nuovo progetto (non uno script piccolino, proprio un progetto di quelli potenzialmente grandi) da zero vi rimando al post di Francesco, che illustra molto bene il tool che viene usato per gestire i progetti in Elixir, Mix, insieme al suo uso più comune, ovvero mix new.

La keyword return in Elixir

Vale la pena spendere due parole, dato che stiamo parlando per la prima volta davvero di funzioni, su come definire i valori di ritorno delle proprie funzioni in Elixir. Al posto di usare return come in tantissimi altri linguaggi, tra cui JavaScript, Java, o Ruby, in Elixir il valore di ritorno di una funzione è semplicemente l’ultima espressione che scriviamo dentro di essa.

Per dare un occhio più approfondito a questa piccola particolarità possiamo definire un modulo che si occupi di fare piccole operazioni sui numeri:

defmodule SimpleMath do
  def divide_by_two(number) do
    number/2
  end

  def square(number) do
    number*number
  end

  def sum_three(number) do
    number+3
  end
end

Salvando questo modulo come simple_math.ex possiamo caricarlo dentro iex e farci degli esperimenti:

iex(1)> import_file("simple_math.ex")
{:module, SimpleMath,
 <<70, 79, 82, 49, 0, 0, 5, 56, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 159,
   0, 0, 0, 17, 17, 69, 108, 105, 120, 105, 114, 46, 83, 105, 109, 112, 108,
   101, 77, 97, 116, 104, 8, 95, 95, 105, 110, ...>>, {:sum_three, 1}}
iex(2)> 4 |> SimpleMath.divide_by_two |> IO.puts
2.0
:ok
iex(3)>

Come vediamo, all’interno delle funzioni ci basta usare un’espressione per identificarla come valore di ritorno. Se volessimo la stringa ciao come valore di ritorno, non dovremmo fare altro che scrivere "ciao" alla fine della funzione. Per chi viene da altri linguaggi questa è una differenza non da poco, dato che Elixir non è strutturato per permettere per esempio i cosiddetti “early return”1 all’interno delle funzioni. Io però con questo meccanismo ho preso confidenza abbastanza in fretta.

Adesso che sappiamo come definire funzioni ma soprattutto come definire moduli dove raccogliere le nostre funzioni, possiamo mantenere il codice ordinato. Non ci resta altro che cominciare con qualche piccolo progettino2.

Vai alla parte 3

Vai alla parte 5

  1. Per chi volesse approfondire, un buon esempio di early return in JavaScript è qua. È una tecnica che uso anch’io, ma in Elixir non si può, e non solo: in realtà per come è strutturato il linguaggio penso aiuti a fattorizzare meglio il codice. Se ne volete parlare, meglio scrivermi o venire al prossimo incontro di Elixir Roma ;-) 

  2. In realtà manca ancora un piccolo pezzettino, confido che lo vedremo presto. Avete visto la piccola magia che ho fatto dentro iex nell’ultimo snippet di codice? Si chiama pipe operator. Ma ne parleremo meglio la prossima volta.