суббота, 28 октября 2017 г.

Ссылка. Erlang

http://learnyousomeerlang.com/content

пятница, 27 октября 2017 г.

Вопрос. Haskell

По итогам:
http://programmingmindstream.blogspot.ru/2017/10/haskell-vs-count.html?m=1

А как length/count (количество элементов списка) на Haskell реализовано?

Так:

Count [] = 0
Count ( _ : xs ) = 1 + Count xs

?

Или можно как-то эффективнее?

четверг, 26 октября 2017 г.

Haskell vs мои скрипты. Count & Map

Integer def List:Count
  List in aList
 aList Match (
  List:[]
   0
  ( List:Make: _ Tail )
   ( 1 + Tail call.me )
 ) // aList Match
; // List:Count

// что тут делать с "длинной рекурсией"
// - пока не очень понятно,
// возможно стоит сделать Count
// "хранимым членом"

Тогда так:

Integer def List:Count
  List in aList
 aList Match (
  List:[]
   0
  ( List:Make: _ Tail Count )
   (
    If ( Count .IsValid ) then
     Count
    Else
     ( 1 + Tail call.me )
   )
 ) // aList Match
; // List:Count

List def List:Map
  List in aList
  Lambda in aLambda
 aList Match (
  List:[]
   List:[]
  ( List:Make: Head Tail )
   List:Make:
     ^@( Head aLambda do )
     ^@( Tail aLambda call.me )
 ) // aList Match
; // List:Map

Ну и вызов:

List:Make 1 List:Make 2 List:Make 3 List:Make 4 List:Make 5 List:[]
 // строим список [ 1 2 3 4 5 ]
IsOdd
 // отбираем нечётные
List:Map
( ToString + ' ' )
 // тут приводим к строке и добавляем пробел
List:Map
List:For:
 // перебирается список
Print
 // печатаем каждый элемент

Напечатано:
1 3 5

Ну и вызов:

List:Make 1 List:Make 2 List:Make 3 List:Make 4 List:Make 5 List:[]
 // строим список [ 1 2 3 4 5 ]
IsOdd
 // отбираем нечётные
List:Map
List:Count
Print
 // печатаем List:Count

Напечатано:
3

Пока выглядит вроде некузяво.

Но у меня же скрипты изначально императивные. И ОПЗ (обратная польская запись).

Но идею я вроде понял. Там строится граф/дерево разбора выражений в узлах которого записывается либо значение, либо ссылка на функцию (возможно со связанными параметрами, и не факт, что со всеми).

Если это значение, то выражение - вычислено полностью.

Если ссылка на функцию, то вычислено не полностью.

Тут и проявляется "ленивость".

Когда в узле вычисляется функция, то в узел записывается результат вычисления вместо ссылки на функцию.

Тут проявляется кеширование результатов. Ранее вычисленные функции - больше не вычисляются. А представляются значениями записанными в узлах графа/дерева.

Ну и код на Haskell:

xs = 1 : map (*2) xs

Выглядит так:

List def xs
 List:Make:
  1
  ( call.me ( 2 * ) List:Map )
; // List:Map

Я честно скажу - не проверял, но должно сработать.

Завтра проверю.

Бесконечной рекурсии там точно не будет.

При вызове xs.

Она сконструирует список:
 1 : reference to expression ( xs ( 2 * ) List:Map )

А вот применится ли  Map к правильному значению - вопрос пока открыт.

Возможно Map будет применяться не к xs, а к 1 ВСЕГДА.

Тут вопрос пока открыт. Надо проверить.

Возможно надо написать так:

List def xs
 List:Make:
  1
  ( Result ( 2 * ) List:Map )
; // List:Map

Есть и такой вариант. И он (как мне кажется) - ближе к истине.

Ибо call.me - это ссылка на функцю, а Result - это уже вычисленное значение.

Тонкая грань.

Или так:

List def xs
  List VAR myResult
 List:Make:
  1
  ( myResult ( 2 * ) List:Map )
 >>> myResult
 myResult
; // List:Map)

Хотя и это можно скрыть за "синтаксическим сахаром".

среда, 25 октября 2017 г.

ToDo. Сделать глобальную writeonly "переменную" _

Сделать глобальную writeonly "переменную" _

WriteOnly _

Туда можно писать, но нельзя читать.

Это аналог devNull.

Это нужно для pattern matching'а.

Update. Сделал.

ToDo. Сделать match вместо RULES

Сделать match:

Чтобы вместо:

VAR head
VAR tail

RULES
 ( aList Empty == )
  Empty
 ( aList .ConstructedWith: List )
  (
   aList .getValues ( @ head @ tail )
   head : tail
  )
 DEFAULT
  aList
 >>> Result
;

Или:


VAR head
VAR tail

RULES
 ( aList .ConstructedWith: Empty )
  Empty
 ( aList .ConstructedWith: List )
  (
   aList .getValues ( @ head @ tail )
   head : tail
  )
 DEFAULT
  aList
 >>> Result
;

Написать:

Match aList
 ( Empty :  Empty )
 ( matched List ( head tail ) : ( head : tail ) )
 ( Default : aList )
 >>> Result
;

Чтобы можно было pattern matching делать.

И переменные (head и tail в нашем случае) определялись в нужном контексте.

Или даже так:

Match aList
 ( Empty ?  Empty )
 ( matched List head tail ? ( head : tail ) )
 ( matched Join head tail ? ( head : tail ) )
 ( Default ? aList )
 >>> Result
;

Или даже так:

Match aList
 ( Empty ?  Empty )
 ( List head tail ? ( head : tail ) )
 ( Join head tail ? ( head : tail ) )
 ( Default ? aList )
 >>> Result
;

Haskell. Pattern matching

checkIP :: IPAddress -> String
checkIP (IPv4 address) = "IPv4 is '" ++ address ++ "'."
checkIP IPv4Localhost  = "IPv4, localhost."
checkIP (IPv6 address) = "IPv6 is '" ++ address ++ "'."
checkIP IPv6Localhost  = "IPv6, localhost."
Очень глубоко на самом деле.

Я давно о подобном думал. А решение оказывается "лежало на поверхности".

вторник, 24 октября 2017 г.

Data 1. Haskell vs мои скрипты

data List = List a List | []

Выглядит так:

Data List
 Constructor List (
  Anonim ANY
  Anonim List
 ) // List

 Constructor [] ()
; // List

Или с именами полей:

Data List
 Constructor List (
  Named ANY Head
  Named List Tail
 ) // List

 Constructor [] ()
; // List

Или в операторном виде:

Data List
 Constructor List (
  Left Anonim ANY // параметр слева
  Anonim List // параметр справа
 ) // List

 Constructor [] ()
; // List

Тогда конструктор List вызывается так:

1 List 2 List []

Строит:

[ 1 2 ]

О! Я понял как pattern matching сделать.

В общем я могу сделать head:tail вместо .Split Head Tail.

 aList .Split Head Tail

Можно сделать так (под капотом):


MATCH List:Make ( Head Tail )


Тут говорим, что надо применить pattern matching к конструктору List:Make и положить результаты в ( Head Tail )


А потом MATCH можно спрятать в и вычислять его в зависимости от того с какой стороны от знака равно (=) находится List:Make.


Учитывая, что "экземпляр объкта" знает про конструктор, которым он был создан, то выражение:


MATCH List:Make ( Head Tail )


можно переписать:



MATCH ( Head Tail )



Тогда навскидку:

LIST FUNCTION f
  LIST IN aList
 ANY VAR Head
 LIST VAR Tail
 aList .Split Head Tail
 LIST:Make 1 Map ( 2 * ) Tail
 >>> Result
; // f

Можно переписать так:


LIST FUNCTION f

  LIST IN aList
 ANY VAR Head
 LIST VAR Tail
 MATCH aList  ( Head Tail )
 LIST:Make 1 Map ( 2 * ) Tail
 >>> Result
; // f


Или даже так:

LIST FUNCTION f
  LIST IN aList
 ANY VAR Head
 LIST VAR Tail
 MATCH aList
  []
   []
  ( Head Tail )
   ( LIST:Make 1 Map ( 2 * ) Tail )
 ; // MATCH
 >>> Result
; // f


Или так:


LIST FUNCTION f
  LIST IN aList
 MATCH aList
  []
   []
  ( ANY VAR Head
    LIST VAR Tail
    Head Tail )
   ( LIST:Make 1 Map ( 2 * ) Tail )
 ; // MATCH
 >>> Result
; // f