Часто (например, в статье Влада про Linq) одним из требований, которому
должна удовлетворять функция, чтобы быть pure function является следующее
требование:
Функция не должна создавать никаких побочных эффектов. Под побочными
эффектами понимается:
....
* Посылать или принимать некие сообщения.
А как же Pid ! {} и receive в Erlang? Правильно ли я понимаю, что это как
раз и есть тот побочный эффект, про который пишет Влад?
Здравствуйте, DemAS, Вы писали:
DAS>Часто (например, в статье Влада про Linq) одним из требований, которому DAS>должна удовлетворять функция, чтобы быть pure function является следующее DAS>требование:
чистая функция — это функция в математическом смысле этого слова
[cut]
DAS>А как же Pid ! {} и receive в Erlang? Правильно ли я понимаю, что это как DAS>раз и есть тот побочный эффект, про который пишет Влад?
Ну не только ! есть же ещё ввод-вывод, например
Эрланг вроде никогда не стремился быть именно "чистым" ФЯ, да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией...
"Курилка" <1546@users.rsdn.ru> writes:
> Ну не только ! есть же ещё ввод-вывод, например
Да, и это тоже. С вводом/выводом понятно, а вот про сообщения хотел уточнить.
> Эрланг вроде никогда не стремился быть именно "чистым" ФЯ, да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией...
Что есть динамическая типизация? Это когда до моменти исполнения нельзя
сказать какого типа значение будет присвоено данной переменной ?
Здравствуйте, DemAS, Вы писали:
DAS>"Курилка" <1546@users.rsdn.ru> writes:
>> Ну не только ! есть же ещё ввод-вывод, например
DAS>Да, и это тоже. С вводом/выводом понятно, а вот про сообщения хотел уточнить.
Дак а чем сообщения от ввода-вывода отличаются принципиально?
Если передача на другую ноду, то в любом случае ввод-вывод будет
>> Эрланг вроде никогда не стремился быть именно "чистым" ФЯ, да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией...
DAS>Что есть динамическая типизация? Это когда до моменти исполнения нельзя DAS>сказать какого типа значение будет присвоено данной переменной ?
Ну хотяб вики посмотри чтоль.
Строго говоря в Эрланге и переменных нет
Да и тип гарантировать вполне можно, ставишь гард на функцию (например is_integer/1)
Здравствуйте, Курилка, Вы писали:
К>... да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией...
Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции.
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, Курилка, Вы писали:
К>>... да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией... PM>Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции.
Ну в теории теория не отличается от практики
Т.е. есть какие-то примеры подобного?
Ну и вопрос будет ли стоить овчинка выделки, в смысле получим ли мы реальные бенефиты и будут ли они больше чем дополнительный гемморой от специальных "извратов".
> DAS>Что есть динамическая типизация? Это когда до моменти исполнения нельзя > DAS>сказать какого типа значение будет присвоено данной переменной ? > > Ну хотяб вики посмотри чтоль.
Извини, а это не то же самое что я сказал? Оно же, если я не ошибаюсь,
называется late/early binding.
Здравствуйте, DemAS, Вы писали:
DAS>"Курилка" <1546@users.rsdn.ru> writes:
>> DAS>Что есть динамическая типизация? Это когда до моменти исполнения нельзя >> DAS>сказать какого типа значение будет присвоено данной переменной ? >> >> Ну хотяб вики посмотри чтоль.
DAS>Извини, а это не то же самое что я сказал? Оно же, если я не ошибаюсь, DAS>называется late/early binding.
Ты задал вопрос, что это есть такое, вот и дал самую элементарную ссылку, которую можно было посмотреть, чтобы узнать.
Раннее/позднее связывание это лишь подробности разрешния имён, но к топику как-то это совсем отношения не имеет.
Здравствуйте, DemAS, Вы писали:
>> чистая функция — это функция в математическом смысле этого слова
DAS>Хороший пример ответа, когда вроде ответил, а топикстартеру понятнее не стало.
Имеются в виду 2 вещи: результат функции зависит только от ее параметров, функция занимается исключительно вычислением своего результата.
Вопрос с побочными эффектами не так прост. Например, в ленивом чистом языке функция может использовать значение переданного ей ленивого аргумента, а может не использовать. В первом случае произойдет его вычисление и обновится его внутренее представление (была некоторая функция, стал резльтат ее вычисления), в каком-то смысле это тоже побочный эффект.
PM>>Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции. К>Т.е. есть какие-то примеры подобного?
Haskell, do notation.
К>Ну и вопрос будет ли стоить овчинка выделки, в смысле получим ли мы реальные бенефиты и будут ли они больше чем дополнительный гемморой от специальных "извратов".
На этот счёт есть разные мнения.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, thesz, Вы писали:
PM>>>Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции. К>>Т.е. есть какие-то примеры подобного?
T>Haskell, do notation.
Это ответ на "как-то контролировать чистоту для языка с динамической типизацией"?
Или я что-то не понял или одно из двух...
Здравствуйте, Курилка, Вы писали:
К>>>... да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией... PM>>Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции.
К>Ну в теории теория не отличается от практики
А кто говорил о практике? Ты сказал дословно "не очень представляю можно ли как-то.." — очевидно, как-то можно. thesz ниже совершенно правильно предложил do-нотацию как вариант _синтаксиса_.
На практике, конечно, смысла мало — приверженцы динамики не оценят.
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, Курилка, Вы писали:
К>>>>... да и как-то не очень представляю можно ли как-то контролировать чистоту для языка с динамической типизацией... PM>>>Теоретически можно, если для операций с побочными эффектами ввести специальные синтаксические конструкции.
К>>Ну в теории теория не отличается от практики PM>А кто говорил о практике? Ты сказал дословно "не очень представляю можно ли как-то.." — очевидно, как-то можно. thesz ниже совершенно правильно предложил do-нотацию как вариант _синтаксиса_.
Дак как оно выглядеть будет не столько интересно, интересно скорее, как оно будет работать. Do нотация требует монаду, которая определяется в компайл-тайме (да и существует тоже по ходу тамже), а что в случае динамической типизации будешь делать?.
Здравствуйте, Курилка, Вы писали:
К> Do нотация требует монаду
Это в Хаскеле она требует монаду, т.к. рассахаривается в вызовы перегруженных функций (>>=) и return. Вполне можно представить себе язык, поддерживающий только одну монаду — IO — и транслирующий do-нотацию соответствующим образом.
Re[6]: proof of concept (очередной игрушечный интерпретатор)
Здравствуйте, Курилка, Вы писали:
К>Дак как оно выглядеть будет не столько интересно, интересно скорее, как оно будет работать. Do нотация требует монаду, которая определяется в компайл-тайме (да и существует тоже по ходу тамже), а что в случае динамической типизации будешь делать?.
Хоть и вряд ли кто-то захочет в горе кода без комментариев разбираться, но тем не менее, вот он, чисто-функциональный динамически-типизированный язык с do-нотацией.
Тадам :
import Text.ParserCombinators.Parsec
-- interpreter coredata Value = VInt Integer | VFun (Value -> Value) | VAction (IO Value)
type Ident = String
data Expr = Const Integer
| Var Ident
| Add Expr Expr
| Fun Ident Expr
| App Expr Expr
| Bind Expr Expr
| Return Expr
deriving Show
type Env = [(Ident, Value)]
eval :: Expr -> Env -> Value
eval (Const x) env = VInt x
eval (Var name) env =
case lookup name env of
Just v -> v
_ -> error ("Unbound variable: " ++ name)
eval (Add e1 e2) env =
case (eval e1 env, eval e2 env) of
(VInt x, VInt y) -> VInt (x+y)
_ -> error"addition: Type error"
eval (Fun name body) env = VFun $ \val -> eval body ((name, val):env)
eval (App f x) env = case (eval f env) of
VFun fv -> fv(eval x env)
_ -> error"function application: Type error"
eval (Bind action fnext) env =
case (eval action env, eval fnext env) of
(VAction m, VFun f) -> VAction $ do x <- m
run (f x)
_ -> error"do block: Type error"
eval (Return e) env = VAction (return (eval e env))
run :: Value -> IO Value
run v@(VInt _) = return v
run v@(VFun _) = return v
run (VAction a) = a >>= run
initEnv = [("print", vprint), ("read", vread)]
where vprint = VFun $ \v -> case v of
VInt x -> VAction (print x >> return (VInt 0))
_ -> error"print: Type error"
vread = VAction (fmap VInt (putStr "Enter an integer: " >> readLn))
runProgram p = run (eval p initEnv)
-- parser
parsePureExpr = parseConst <|> parseAdd <|> try parseApp <|> parseVar
parseExpr = try parseDoBlock <|> parsePureExpr
skipSpaces = many space
parseConst = do
s <- many1 digit
skipSpaces
return (Const (read s))
parseIdent = do
s <- many1 letter
skipSpaces
return s
parseVar = fmap Var parseIdent
parseApp = do
func <- parseVar
char_ '('
arg <- parsePureExpr
char_ ')'
return (App func arg)
char_ c = char c >> skipSpaces
string_ s = string s >> skipSpaces
parseAdd = do
char_ '('
x <- parsePureExpr
char_ '+'
y <- parsePureExpr
char_ ')'
return (Add x y)
parseDefun = do
string_ "fun"
fname <- parseIdent
argname <- parseIdent
char_ '='
body <- parseExpr
char_ ';'
return (fname, Fun argname body)
parseDoBlock = do
string_ "do"
char_ '{'
stmts <- many1 parseStatement
char '}'let ("_", lastStmt) = last stmts
return (foldr bind lastStmt (init stmts))
where bind (v, e1) e2 = Bind e1 (Fun v e2)
parseStatement = try parseBinding <|> parseSimpleStatement
parseBinding = do
var <- parseIdent
string_ "<-"
rhs <- parsePureExpr
char_ ';'
return (var, rhs)
parseSimpleStatement =
try (do string_ "return"
e <- parsePureExpr
return ("_", (Return e))) <|>
(do e <- parsePureExpr
char_ ';'
return ("_", e))
parseProgram = do
funs <- many parseDefun
main_ <- parseDoBlock
return (foldr addDefun main_ funs)
where addDefun (name, fun) prog = App (Fun name prog) fun
runProgramParser = runParser parseProgram () ""
parseAndRun ptext = case runProgramParser ptext of
Right p -> runProgram p
Left e -> error (show e)
-- tests
testOk1 =
parseAndRun $ unlines $ ["fun foo x = (x + 1); ",
"fun bar x = (x + 42); ",
"fun bzzt x = do { print(x); print(777); };",
"do { x <- read; ",
" print(foo(x)); ",
" bzzt(x); ",
" print(bar(x));} " ]
testOk2 =
parseAndRun $ unlines $ ["fun action x = do { return (x + 1) };",
"do { z <- action(42); print(z); } "]
testError =
parseAndRun $ unlines $ ["fun action x = do { return (x + 1) };",
"do { print( (action(10) + 5) ); } "]
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, Курилка, Вы писали:
К>> Do нотация требует монаду PM>Это в Хаскеле она требует монаду, т.к. рассахаривается в вызовы перегруженных функций (>>=) и return. Вполне можно представить себе язык, поддерживающий только одну монаду — IO — и транслирующий do-нотацию соответствующим образом.
Чувствую полноценного ответа ожидать не приходится...
Ну скажи как твоя только одна монада будет (цитирую изначальную проблему, которую я высказал) "контролировать чистоту для языка"?
Здравствуйте, Курилка, Вы писали:
К>Ну скажи как твоя только одна монада будет (цитирую изначальную проблему, которую я высказал) "контролировать чистоту для языка"?
я гнева вашего никак не растолкую...
самое простое — запрет на вызов процедур (имеющих побочные эффекты) из функций. и всё. даже никаких спец. синт. конструкций не понадобится
Люди, я люблю вас! Будьте бдительны!!!
Re[7]: proof of concept (очередной игрушечный интерпретатор)
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, Курилка, Вы писали:
К>>Дак как оно выглядеть будет не столько интересно, интересно скорее, как оно будет работать. Do нотация требует монаду, которая определяется в компайл-тайме (да и существует тоже по ходу тамже), а что в случае динамической типизации будешь делать?.
PM>Хоть и вряд ли кто-то захочет в горе кода без комментариев разбираться, но тем не менее, вот он, чисто-функциональный динамически-типизированный язык с do-нотацией.
[cut]
Клёва, только контроля нету
Хотя прикрутить, конечно можно