manywaypark's Blog
개발, 검색, 함수

'expression'에 해당되는 글 2건

  1. 2015.04.07 erlang string to term or expr
  2. 2011.09.22 Erlang Expressions - if, case, guard

erlang string to term or expr

함수형 언어/Erlang 2015. 4. 7. 16:41 by manywaypark

string to term:

ErlTerms = "{a,b,c,d}.".

{ok,Tokens,_} = erl_scan:string(ErlTerms).

{ok,Term} = erl_parse:parse_term(Tokens).

Term -> {a,b,c,d}.


string to expression (and eval):

StrTerm = "fun() -> result_atom end.".

{ok,Tokens,_} = erl_scan:string(StrTerm).

{ok,[Expr]} = erl_parse:parse_exprs(Tokens).

erl_eval:expr(Expr,[]).

resulted in: {value,#Fun,[]}


refs:

https://github.com/skruger/Surrogate/issues/3

http://stackoverflow.com/questions/1974236/string-to-abstract-syntax-tree

http://stackoverflow.com/questions/2008777/convert-a-string-into-a-fun


happy hackin'

Erlang의 풍부한 표현 방법을 보여주기 위한 간단한 예제를 만들었다.
lists:map에 전달하는 첫번째 파라미터(함수) 부분의 표현 방법을 보면 된다. 

by_...
function은  리스트를 입력받아 각 요소가 홀수인지 짝수인지 판별한다 (에러 처리 포함).
@spec (by_...([integer() | any()]) -> [odd | even | error].

기본적으로 유념해야 할 것은,
  • if는 guard expression을 사용하고, case는 pattern matching을 사용한다.
  • if는 마지막에 truecase는 마지막에 underscore(_) 또는 Any를 사용하여 default(catch all) 조건을 만든다.
  • guard의 and는 comma(,)이고, or는 semicolon(;)이다.

자세한 것은 코드 참조.

%%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: nil -*-
%%%-------------------------------------------------------------------
%%% File    : expressions.erl
%%% Author  : M.W. Park <manywaypark@gmail.com>
%%% Description : an erlang example (to explain expressions)
%%%               ref: http://www.erlang.org/doc/reference_manual/expressions.html
%%%
%%% Created : 2011-09-22 목요일 by M.W. Park
%%%-------------------------------------------------------------------

-module(expressions).
%% -export([]).
%% -import(, []).
-compile(export_all).

%% using guard inside 'if'
by_if(L) when is_list(L) ->
    lists:map(fun(X) ->
                      if
                          is_integer(X),
                          X rem 2 =:= 0 -> even;
                          is_integer(X) -> odd;
                          true          -> error
                      end
              end,
              L).

%% nested 'case'
by_case(L) when is_list(L) ->
    lists:map(fun(X) ->
                      case is_integer(X) of
                          true ->
                              case X rem 2 of
                                  0 -> even;
                                  _ -> odd
                              end;
                          _ -> error
                      end
              end,
              L).

%% 'case' w/ guards
by_case_with_guard(L) when is_list(L) ->
    lists:map(fun(X) ->
                      case X of
                          _ when is_integer(X),
                                 X rem 2 =:= 0 -> even;
                          _ when is_integer(X) -> odd;
                          _                    -> error
                      end
              end,
              L).

%% 'case' w/ exception
%% 'rem' operator may throw an exception.
by_case_with_ex(L) when is_list(L) ->
    lists:map(fun(X) ->
                      try 
                          case X rem 2 of
                              0 -> even;
                              _ -> odd
                          end
                      catch
                          _:_ -> error
                      end
              end,
              L).

%% pattern matching functions
'what?'(X) when is_integer(X), X rem 2 =:= 0 ->
    even;
'what?'(X) when is_integer(X) ->
    odd;
'what?'(_) ->
    error.

%% passing function name as a parameter
by_passing_fun(L) when is_list(L) ->
    lists:map(fun 'what?'/1, L).

%% anonymous function w/ guards
by_anonymous_fun(L) when is_list(L) ->
    lists:map(fun(X) when is_integer(X),
                          X rem 2 =:= 0 -> even;
                 (X) when is_integer(X) -> odd;
                 (_)                    -> error
              end,
              L).

%% mixture of anonymous function w/ a guard and 'case'
by_mix(L) when is_list(L) ->
    lists:map(fun(X) when is_integer(X) ->
                      case X rem 2 of
                          0 -> even;
                          _ -> odd
                      end;
                 (_) -> error
              end,
              L).

%%%-------------------------------------------------------------------
%%% Unit Tests
%%%-------------------------------------------------------------------
-include_lib("eunit/include/eunit.hrl").

-define(BASIC(FunName), ?_assertEqual([odd, even], FunName(lists:seq(1, 2)))).
-define(ERROR(FunName), ?_assertEqual([error, error], FunName([0.1, atom]))). 

by_if_test_() ->
    [
     ?BASIC(by_if),
     ?ERROR(by_if)
    ].

by_case_test_()->
    [
     ?BASIC(by_case),
     ?ERROR(by_case)
    ].

by_case_with_guard_test_() ->
    [
     ?BASIC(by_case_with_guard),
     ?ERROR(by_case_with_guard)
    ].

by_case_with_ex_test_() ->
    [
     ?BASIC(by_case_with_ex),
     ?ERROR(by_case_with_ex)
    ].

by_passing_fun_test_() ->
    [
     ?BASIC(by_passing_fun),
     ?ERROR(by_passing_fun)
    ].

by_anonymous_fun_test_() ->
    [
     ?BASIC(by_anonymous_fun),
     ?ERROR(by_anonymous_fun)
    ].

by_mix_test_() ->
    [
     ?BASIC(by_mix),
     ?ERROR(by_mix)
    ].

happy hackin'
1 
분류 전체보기 (306)
잡담 (20)
함수형 언어 (65)
emacs (16)
java (18)
tips & tricks (154)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

04-20 03:34