SlideShare une entreprise Scribd logo
1  sur  131
Télécharger pour lire hors ligne
am s
    gr g
 ro in
P it
     r
 W rams
 P r og
Code generation
•   XDoclet

•   XText

•   Lombock

•   Velocity, Erb

•   MDA

•   Rails

•   Hacks
p
p
C
Many moons ago

  #define foo "salad

  int main(int argc, char* argv[]) {
      printf(foo bar");
      return EXIT_SUCCESS;
  }

  ; salad bar
Many moons ago

  #define foo "salad

  int main(int argc, char* argv[]) {
      printf(foo bar");
      return EXIT_SUCCESS;
  }

  ; salad bar

                            (foo bar”);

            ZOMG!
Fixed?

#define foo "salad”

int main(int argc, char* argv[]) {
    printf(“foo bar");
    return EXIT_SUCCESS;
}

; foo bar
Hating expressions
   #define discr(a,b,c) b*b-4*a*c

   int main(int argc, char* argv[]) {
       int x=1, y=2;
       printf(2*discr(x-y, x+y, x-y)*5);
       return EXIT_SUCCESS;
   }

   ; ??
Hating expressions
   #define discr(a,b,c) b*b-4*a*c

   int main(int argc, char* argv[]) {
       int x=1, y=2;
       printf(2*discr(x-y, x+y, x-y)*5);
       return EXIT_SUCCESS;
   }

   ; ??

                   2*x+y*x+y-4*x-y*x-y*5
Hating expressions
   #define discr(a,b,c) b*b-4*a*c

   int main(int argc, char* argv[]) {
       int x=1, y=2;
       printf(2*discr(x-y, x+y, x-y)*5);
       return EXIT_SUCCESS;
   }

   ; ??

           (2*x)+(y*x)+y-(4*x)-(y*x)-(y*5)
Hating expressions
   #define discr(a,b,c) b*b-4*a*c

   int main(int argc, char* argv[]) {
       int x=1, y=2;
       printf(2*discr(x-y, x+y, x-y)*5);
       return EXIT_SUCCESS;
   }

   ; ??

             2*(x+y)*(x+y)-4*(x-y)*(x-y)*5
Fixed?
#define discr(a,b,c) b*b-4*a*c

int main(int argc, char* argv[]) {
    int x=1, y=2;
    printf(2*discr(x-y, x+y, x-y)*5);
    return EXIT_SUCCESS;
}

; ??

       discr(a,b,c) ((b)*(b)-4*(a)*(c))
FX
#define discr(a,b,c) b*b-4*a*c

int main(int argc, char* argv[]) {
    int x=1, y=2;
    printf(2*discr(x-y, x--, x-y)*5);
    return EXIT_SUCCESS;
}

; ??

          2*(x--)*(x--)-4*(x-y)*(x-y)*5
l
C++
Fact!
template <int N>
struct Factorial
{
    enum { value = N * Factorial<N-1>::value };
};

template <>
struct Factorial<1>
{
    enum { value = 1 };
};

// example use
int main()
{
    const int fact5 = Factorial<15>::value;
    std::cout << fact5 << endl;
    return 0;
}

// 120
Böhm and Jacopini
template <>
struct AValue<>
{
    enum { value = 42 };
};


       values
Böhm and Jacopini
                           template <int X, int Y>
                           struct AFunction
template <>
                           {
struct AValue<>
                               enum { result = X + Y };
{
                           };
    enum { value = 42 };
};
                           AFunction<1, 2>::result

       values
                           //=> 3

                                    functions
Böhm and Jacopini
                                               template <int X, int Y>
                                               struct AFunction
     template <>
                                               {
     struct AValue<>
                                                   enum { result = X + Y };
     {
                                               };
         enum { value = 42 };
     };
                                               AFunction<1, 2>::result

            values
                                               //=> 3

                                                        functions
template <bool cond, class Then, class Else>
struct If
{
    typedef Then RET;
};

template <class Then, class Else>
struct If<false, Then, Else>
{
    typedef Else RET;
};

         branching
Böhm and Jacopini
                                                  template <int X, int Y>
                                                  struct AFunction
     template <>
                                                  {
     struct AValue<>
                                                      enum { result = X + Y };
     {
                                                  };
         enum { value = 42 };
     };
                                                  AFunction<1, 2>::result

            values
                                                  //=> 3

                                                           functions
template <bool cond, class Then, class Else>   template <int N>
struct If                                      struct Recur
{                                              {
    typedef Then RET;                             enum { result = N * Recur<N-1>::result };
};                                             };

template <class Then, class Else>              template <>
struct If<false, Then, Else>                   struct Recur<0>
{                                              {
    typedef Else RET;                              enum { result = 1};
};                                             };

         branching                                          recursion
Böhm and Jacopini
                                                  template <int X, int Y>
                                                  struct AFunction
     template <>
                                                  {
     struct AValue<>
                                                      enum { result = X + Y };
     {



                      ring
                                                  };



                   Tu
         enum { value = 42 };
     };
                                                  AFunction<1, 2>::result

            values
                                                  //=> 3




                           ness
                             functions
struct If
{                Com plete
template <bool cond, class Then, class Else>   template <int N>
                                               struct Recur
                                               {
    typedef Then RET;                             enum { result = N * Recur<N-1>::result };
};                                             };

template <class Then, class Else>              template <>
struct If<false, Then, Else>                   struct Recur<0>
{                                              {
    typedef Else RET;                              enum { result = 1};
};                                             };

         branching                                          recursion
Böhm and Jacopini
                                                  template <int X, int Y>
                                                  struct AFunction
     template <>
                                                  {
     struct AValue<>
                                                      enum { result = X + Y };
     {
                                                  };
         enum { value = 42 };
     };
                                                  AFunction<1, 2>::result

            values
                                                  //=> 3

                                                           functions
template <bool cond, class Then, class Else>   template <int N>
struct If                                      struct Recur
{                                              {
    typedef Then RET;                             enum { result = N * Recur<N-1>::result };
};                                             };

template <class Then, class Else>              template <>
struct If<false, Then, Else>                   struct Recur<0>
{                                              {
    typedef Else RET;                              enum { result = 1};
};                                             };

         branching                                          recursion
q
OC aml
From this...
List.map (fun x -> x+1) [1; 2; 3]
To this...
            List.map (fun x -> x+1) [1; 2; 3]




ExApp (loc, ExApp (loc, ExAcc (loc,
   ExUid (loc, "List"), ExLid (loc, "map")),
     ExFun (loc, [(PaLid (loc, "x"), None,
       ExApp (loc, ExApp (loc, ExLid (loc, "+"),
         ExLid (loc, "x")), ExInt (loc, "1")))])),
   ExApp (loc, ExApp (loc, ExUid (loc, "::"),
    ExInt (loc, "1")),
     ExApp (loc, ExApp (loc, ExUid (loc, "::"),
       ExInt (loc, "2")), ExApp (loc,
         ExApp (loc, ExUid (loc, "::"), ExInt (loc, "3")),
         ExUid (loc, "[]")))))
Just this...
List.map (fun x -> x+1) [1; 2; 3]
Well, this...
      List.map (fun x -> x+1) [1; 2; 3]




<:expr< List.map (fun x -> x+1) [1; 2; 3] >>
The expander
      List.map (fun x -> x+1) [1; 2; 3]




<:expr< List.map (fun x -> x+1) [1; 2; 3] >>




           camlp4::expr
1927.09.04 - 2011.10.23
Lisp Macros
Use cases
•   Creating binding forms

•   Control !ow




•   Icing
History
LISP
(label eval (lambda (expr binds)
              (cond
                ((atom expr) (assoc expr binds))
                ((atom (car expr))
                 (cond
                    ((eq (car expr) (quote quote)) (cadr expr))
                    ((eq (car expr) (quote atom)) (atom     (eval (cadr expr) binds)))
                    ((eq (car expr) (quote eq))    (eq      (eval (cadr expr) binds)
                                                            (eval (caddr expr) binds)))
                    ((eq (car expr) (quote car))   (car     (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cdr))   (cdr     (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cons)) (cons     (eval (cadr expr) binds)
                                                            (eval (caddr expr) binds)))
                    ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds))
                    (t (eval (cons (assoc (car expr) binds)
                                   (cdr expr))
                             binds))))
                ((eq (caar expr) (quote label))
                 (eval (cons (caddar expr) (cdr expr))
                        (cons (list (cadar expr) (car expr)) binds)))
                ((eq (caar expr) (quote lambda))
                 (eval (caddar expr)
                        (append (pair (cadar expr) (eval-args (cdr expr) binds))
                                binds)))
                (t (assoc expr binds)))))
AIM-57


•   MACRO De"nitions in LISP

•   by Timothy Hart

•   1963
LISP with macros
(label eval (lambda (expr binds)
              (cond
                ((atom expr) (assoc expr binds))
                ((atom (car expr))
                 (cond
                    ((eq (car expr) (quote quote)) (cadr expr))
                    ((eq (car expr) (quote atom)) (atom      (eval (cadr expr) binds)))
                    ((eq (car expr) (quote eq))      (eq     (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote car))     (car    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cdr))     (cdr    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cons)) (cons      (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds))
                    (t (eval (cons (assoc (car expr) binds)
                                   (cdr expr))
                             binds))))
                ((eq (caar expr) (quote label))
                 (eval (cons (caddar expr) (cdr expr))
                        (cons (list (cadar expr) (car expr)) binds)))
                ((eq (caar expr) (quote lambda))
                 (eval (caddar expr)
                        (append (pair (cadar expr) (eval-args (cdr expr) binds))
                                binds)))
                ((eq (caar expr) (quote macro))
                 (cond
                    ((eq (cadar expr) (quote lambda))
                     (eval (eval (car (cdddar expr))
                                 (cons (list (car (caddar expr))
                                                (cadr expr))
                                        binds))
                           binds)))))))
LISP with macros
(label eval (lambda (expr binds)
              (cond
                ((atom expr) (assoc expr binds))
                ((atom (car expr))
                 (cond
                    ((eq (car expr) (quote quote)) (cadr expr))
                    ((eq (car expr) (quote atom)) (atom      (eval (cadr expr) binds)))
                    ((eq (car expr) (quote eq))      (eq     (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote car))     (car    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cdr))     (cdr    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cons)) (cons      (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds))
                    (t (eval (cons (assoc (car expr) binds)
                                   (cdr expr))
                             binds))))
                ((eq (caar expr) (quote label))
                 (eval (cons (caddar expr) (cdr expr))
                        (cons (list (cadar expr) (car expr)) binds)))
                ((eq (caar expr) (quote lambda))
                 (eval (caddar expr)
                        (append (pair (cadar expr) (eval-args (cdr expr) binds))
                                binds)))
                ((eq (caar expr) (quote macro))
                 (cond
                    ((eq (cadar expr) (quote lambda))
                     (eval (eval (car (cdddar expr))
                                 (cons (list (car (caddar expr))
                                                (cadr expr))
                                        binds))
                           binds)))))))
LISP with macros
(label eval (lambda (expr binds)
              (cond
                ((atom expr) (assoc expr binds))
                ((atom (car expr))
                 (cond
                    ((eq (car expr) (quote quote)) (cadr expr))
                    ((eq (car expr) (quote atom)) (atom      (eval (cadr expr) binds)))
                    ((eq (car expr) (quote eq))      (eq     (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote car))     (car    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cdr))     (cdr    (eval (cadr expr) binds)))
                    ((eq (car expr) (quote cons)) (cons      (eval (cadr expr) binds)
                                                             (eval (caddr expr) binds)))
                    ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds))
                    (t (eval (cons (assoc (car expr) binds)
                                   (cdr expr))
                             binds))))
                ((eq (caar expr) (quote label))
                 (eval (cons (caddar expr) (cdr expr))
                        (cons (list (cadar expr) (car expr)) binds)))
                ((eq (caar expr) (quote lambda))
                 (eval (caddar expr)
                        (append (pair (cadar expr) (eval-args (cdr expr) binds))
                                binds)))
                ((eq (caar expr) (quote macro))
                 (cond
                    ((eq (cadar expr) (quote lambda))
                     (eval (eval (car (cdddar expr))
                                 (cons (list (car (caddar expr))
                                                (cadr expr))
                                        binds))
                           binds)))))))
Lightweight fn/blocks
(defmacro when-not                            def when_not(condition, &blk)
                                                yield unless condition
                                control !ow
  [condition & body]
  `(when (not ~condition)                     end
     ~@body))
                                              when_not(1.even?) {
(when-not (even? 1)                             puts "not even"
  (println “not even))                        }
;; not even                                   ## not even



                                              module Enumerable
                                                def scope &blk
(defmacro scope
                                                  yield *(self.to_a)
  [vals names & body]
  `(let [[~@names] ~vals]         bindings      end
                                              end
    ~@body))
                                              (0..20).scope { | a, b |
(scope (range) [a b]
                                                puts "#{a} and #{b}"
 (println (str a " and " b)))
                                              }
;; 0 and 1
                                              ## 0 and 1
Baysick
object Lunar extends Baysick {
  def main(args:Array[String]) = {
     20 LET ('dist := 100)
     30 LET ('v := 1)
     40 LET ('fuel := 1000)
     50 LET ('mass := 1000)
     60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
     80 PRINT "Each turn you must decide how much fuel to burn."
     90 PRINT "To accelerate enter a positive number, to decelerate a negative"
    100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
    110 INPUT 'burn
    120 IF ABS('burn) <= 'fuel THEN 150
    130 PRINT "You don't have that much fuel"
    140 GOTO 100
    150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
    160 LET ('fuel := 'fuel - ABS('burn))
    170 LET ('dist := 'dist - 'v)
    180 IF 'dist > 0 THEN 100
    190 PRINT "You have hit the surface"
    200 IF 'v < 3 THEN 240
    210 PRINT "Hit surface too fast (" % 'v % ")km/s"
    220 PRINT "You Crashed!"
    230 GOTO 250
    240 PRINT "Well done!"
    250 END
    RUN
  }
}
Symbol
                                   Baysick
   Symbol
         object Lunar extends Baysick {
           def main(args:Array[String]) = {
              20 LET ('dist := 100)
              30 LET ('v := 1)
    Symbol    40 LET ('fuel := 1000)
              50 LET ('mass := 1000)
              60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
              80 PRINT "Each turn you must decide how much fuel to burn."
  Symbol      90 PRINT "To accelerate enter a positive number, to decelerate a negative"
             100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
             110 INPUT 'burn
             120 IF ABS('burn) <= 'fuel THEN 150
 Symbol
             130 PRINT "You don't have that much fuel"
             140 GOTO 100
Symbol       150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
             160 LET ('fuel := 'fuel - ABS('burn))
             170 LET ('dist := 'dist - 'v)
             180 IF 'dist > 0 THEN 100
             190 PRINT "You have hit the surface"
             200 IF 'v < 3 THEN 240
             210 PRINT "Hit surface too fast (" % 'v % ")km/s"
             220 PRINT "You Crashed!"
             230 GOTO 250
             240 PRINT "Well done!"
             250 END
             RUN
           }
         }
Symbol
                                    Baysick
   Symbol
         object Lunar extends Baysick {
           def main(args:Array[String]) = {
              20 LET ('dist := 100)
              30 LET ('v := 1)
    Symbol    40 LET ('fuel := 1000)
              50 LET ('mass := 1000)
              60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
              80 PRINT "Each turn you must decide how much fuel to burn."
  Symbol      90 PRINT "To accelerate enter a positive number, to decelerate a negative"
             100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
             110 INPUT 'burn
             120 IF ABS('burn) <= 'fuel THEN 150
 Symbol
             130 PRINT "You don't have that much fuel"
             140 GOTO 100
Symbol       150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
             160 LET ('fuel := 'fuel - ABS('burn))
             170 LET ('dist := 'dist - 'v)
             180 IF 'dist > 0 THEN 100
             190 PRINT "You have hit the surface"              Implicit    Implicit           Implicit
             200 IF 'v < 3 THEN 240
             210 PRINT "Hit surface too fast ("Implicit% ")km/s"
                                                 % 'v
             220 PRINT "You Crashed!"
             230 GOTO 250
             240 PRINT "Well done!"          Implicit        Implicit
             250 END
             RUN
           }
         }


                         Implicit
Symbol
                                        Baysick
       Symbol
               object Lunar extends Baysick {
                 def main(args:Array[String]) = {
                    20 LET ('dist := 100)
                    30 LET ('v := 1)
          Symbol    40 LET ('fuel := 1000)
                    50 LET ('mass := 1000)
                    60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
                    80 PRINT "Each turn you must decide how much fuel to burn."
        Symbol      90 PRINT "To accelerate enter a positive number, to decelerate a negative"
                   100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
                   110 INPUT 'burn
                   120 IF ABS('burn) <= 'fuel THEN 150
      Symbol
                   130 PRINT "You don't have that much fuel"
                   140 GOTO 100
     Symbol        150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
Closure            160 LET ('fuel := 'fuel - ABS('burn))
                   170 LET ('dist := 'dist - 'v)
                   180 IF 'dist > 0 THEN 100
                   190 PRINT "You have hit the surface"              Implicit    Implicit           Implicit
                   200 IF 'v < 3 THEN 240
                   210 PRINT "Hit surface too fast ("Implicit% ")km/s"
                                                       % 'v
                   220 PRINT "You Crashed!"
                   230 GOTO 250
                   240 PRINT "Well done!"          Implicit        Implicit
 Closure           250 END
                   RUN
                 }
               }


                             Implicit
Map lookup
                                        Map lookup




       Symbol
                                        Baysick
       Symbol
               object Lunar extends Baysick {                   Map lookup
                 def main(args:Array[String]) = {
                    20 LET ('dist := 100)
                    30 LET ('v := 1)
          Symbol    40 LET ('fuel := 1000)
                    50 LET ('mass := 1000)
                    60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
                    80 PRINT "Each turn you must decide how much fuel to burn."
        Symbol      90 PRINT "To accelerate enter a positive number, to decelerate a negative"
                   100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
                   110 INPUT 'burn
                   120 IF ABS('burn) <= 'fuel THEN 150
      Symbol
                   130 PRINT "You don't have that much fuel"
                   140 GOTO 100
     Symbol        150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
Closure            160 LET ('fuel := 'fuel - ABS('burn))
                   170 LET ('dist := 'dist - 'v)
                   180 IF 'dist > 0 THEN 100
                   190 PRINT "You have hit the surface"              Implicit    Implicit           Implicit
                   200 IF 'v < 3 THEN 240
                   210 PRINT "Hit surface too fast ("Implicit% ")km/s"
                                                       % 'v
                   220 PRINT "You Crashed!"
                   230 GOTO 250
                   240 PRINT "Well done!"          Implicit        Implicit
 Closure           250 END
                   RUN
                 }
               }


                             Implicit
Map lookup
                                        Map lookup




       Symbol
                                        Baysick
       Symbol
               object Lunar extends Baysick {                   Map lookup
                 def main(args:Array[String]) = {
                    20 LET ('dist := 100)
                    30 LET ('v := 1)
          Symbol    40 LET ('fuel := 1000)
                    50 LET ('mass := 1000)
                    60 PRINT "You are a in control of a lunar lander, drifting towards the moon."
                    80 PRINT "Each turn you must decide how much fuel to burn."
        Symbol      90 PRINT "To accelerate enter a positive number, to decelerate a negative"
                   100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel
                   110 INPUT 'burn
                   120 IF ABS('burn) <= 'fuel THEN 150
      Symbol
                   130 PRINT "You don't have that much fuel"
                   140 GOTO 100
     Symbol        150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
Closure            160 LET ('fuel := 'fuel - ABS('burn))
                   170 LET ('dist := 'dist - 'v)
                   180 IF 'dist > 0 THEN 100
                   190 PRINT "You have hit the surface"              Implicit    Implicit           Implicit
                   200 IF 'v < 3 THEN 240
                   210 PRINT "Hit surface too fast ("Implicit% ")km/s"
                                                       % 'v
                   220 PRINT "You Crashed!"
                   230 GOTO 250
                   240 PRINT "Well done!"          Implicit        Implicit
 Closure           250 END
                   RUN

               }
                 }                                                   TRAMPOLINE!!!

                             Implicit
Mapping
Dilemma
One of the issues here is
actually encapsulation:
without macros, the
ability to create
abstractions is limited
by the degree to which
underlying language
constructs peek through
the abstraction barrier.
Use cases
•   Creating binding forms

•   Control !ow




•   Icing
“All legitimate uses of
macros are legitimate”
                  — Yogi Berra
Use cases
•   Creating binding forms

•   Control !ow

•   Abstraction

•   Transformation (Houdini, boilerplate)

•   Optimization

•   True power awesomeness

•   Icing
Think
What do you want?


•   A way to de"ne local bindings

•   Properly scoped
Do you need a macro?
  (defn build-memoizer
    ([cache-factory f & args]
       (let [cache (atom (apply cache-factory f args))]
         (with-meta
          (fn [& args]
            (let [cs (swap! cache through f args)]
              @(fogus.clache/lookup cs args)))
          {:unk cache
           :unk-orig f}))))

  ;; usage

  (defn memo
    ([f] (memo f {}))
    ([f seed]
       (build-memoizer
         basic-cache-factory
         f
         seed)))
What does it look like?

        (LET ([rise 1]
              [run 2])
          (/ rise run))

        ;=> 1/2
What is it really?

     ((fn [rise]
         ((fn [run]
            (/ rise run))
          2))
      1)

     ;=> 1/2
Type

(defn foldr [f acc [h & t]]
  (if h
    (f h (foldr f acc t))
    acc))

(defmacro LET [bindings & body]
  (foldr (fn [[n v] subexpr]
           `((fn [~n] ~subexpr) ~v))
         `(do ~@body)
         bindings))
Quick Tip:
binding idiom
(defmacro LET* [bindings & body]
  (assert (vector? bindings))
  (foldr (fn [[n v] subexpr]
           `((fn [~n] ~subexpr) ~v))
         `(do ~@body)
         (partition 2 bindings)))

(LET [rise 1
      run 2]
  (/ rise run))

;=> 1/2
Hygiene
Hygiene
                  An hygienic macro is one where the meanings of symbols that aren't
parameters to the macro are bound at the de!nition site rather than the expansion site.
                                             — James Iry @ Lambda the Ultimate
Degenerative Case 1
  (defmacro tis-true? [a]
    `(when a
       :twas-true))

  ;; somewhere
  (def a false)

  ;; somewhere else
  (tis-true? true)
  ;=> nil
Degenerative Case 1


     (when my-ns/a
       :twas-true)
Degenerative Case 1

  (defmacro tis-true? [a]
    `(when ~a
       :twas-true))

  (tis-true? true)
  ;=> :twas-true
vs.
Degenerative Case 2
(defmacro awhen
  [condition & body]
  `(if-let [~'it ~condition]
     ~@body))

(awhen (:a {:a 42})
  (println it))
; 42
Degenerative Case 2
(defmacro awhen
  [condition & body]
  `(if-let [~'it ~condition]
     ~@body))

(awhen (:a {:a 42})
  (println it))
; 42
Degenerative Case 2

   (def it :not-it)

   (awhen (:a {:a 42})
     (println it))
   ; 42
Better

(def it :not-it)

(when-let [it (:a {:a 42})]
  (println it))
; 42
~’
vs.
Use
Use




Abuse
DSL
Domain-speci"c Languages
MSL
Mood-speci"c Languages
          -- Ian Piumarta
Trammel
Step 0:
    What did I want?
• Goals
 • New :pre/:post syntax
 • Decomplected contracts
 • Invariants on records, types,
    references
 • Better error reporting
 • Misc.
Step 1:
Did I need a macro?


       Yes.
Step 1:
Did I need a macro?


       Yes.
Second-class
   Forms
Macros are first-class at
making second-class forms
    (defrecord Date [year month day])

    (defn Date? [d] (= klass (type d)))

    (defn new-Date
      [& {:or {year 1970, month 1, day 1},
          :as m,
          :keys [year month day]}]
      {:pre [(every? number? [year month day])
             (< month 13)
             (> month 0)
             (< day 32)
             (> day 0)]}
      (->
        (Date. 1970 1 1)
        (merge m)))
Macros
Why Wait for Rich?
Trammel is...
New :pre/:post Syntax

(defconstrainedfn sqr
  [n],[number? (not= 0 n) => pos? number?]
  (* n n))
Trammel is...
   Decomplected Contracts
(defn gregorian-last-day-of-month
  ([d] (gregorian-last-day-of-month (:month d) (:year d)))
  ([month year]
     (if (and (= month 2)
              (leap-year? year))
       29
       (nth *canonical-days* (dec month)))))

(provide/contracts
 [gregorian-last-day-of-month
  "Gregorian last day calculation constraints"
  [d]   [Date? :month :year => number? pos?]
  [m y] [all-positive? => number? pos?]])
Trammel is...
           Record Invariants


  (defconstrainedrecord Date [year 1970 month 1 day 1]
    [(every? number? [year month day])
     (< month 13) (> month 0)
     (< day 32) (> day 0)])



(new-Date :month 11 :day 12 :year “AD”)

;; Assert failed: (every? number? [year month day])
Trammel is...
Better Error Reporting

   (sqr 10)
   ;=> 100

   (sqr :a)
   ; Pre-condition Error: (pos? :a)

   (sqr 0)
   ; Post-condition Error: (pos? 0)
Piecewise
Transformation
Piecewise
       Transformation
(defmacro defconstrainedfn
  [name & body]
  (let [mdata (if (string? (first body))
                 {:doc (first body)}
                 {})
        body (if (:doc mdata)
                 (next body)
                 body)
        body (if (vector? (first body))
                 (list body)
                 body)
        body (for [[args cnstr & bd] body]
                 (list* args
                        (if (vector? cnstr)
                          (second (build-cnstr-map args cnstr))
                          cnstr)
                        bd))]
    `(defn ~name
       ~(str (:doc mdata))
       ~@body)))
Piecewise
  Transformation
(defmacro defmulti
  [mm-name & options]
  (let [docstring   (if (string? (first options))
                      (first options)
                      nil)
        options     (if (string? (first options))
                      (next options)
                      options)
        m           (if (map? (first options))
                      (first options)
                      {})
        options     (if (map? (first options))
                      (next options)
                      options)
        dispatch-fn (first options)
        options     (next options)
        m           (if docstring
                      (assoc m :doc docstring)
                      m)
  ...)
Piecewise
Transformation
         as-futures


 (as-futures [<arg-name> <all-args>]
   <actions-using-arg-name>
   :as <results-name>
  =>
   <actions-using-results>)
Piecewise
Transformation
         as-futures
  (defn sum-facts [& ns]
    (as-futures [n ns]
      (reduce * (range 1 n))
      :as results
     =>
     (reduce #(+ % (deref %2))
             0
             results)))

  (sum-facts 100 13 123 56 33)
  ;=>
  98750442008336013624115798714482080125644041
  37071685821402414202949370696061281065394095
  61103888585087569526895318024046688120956989
  53738011044836999122093443893501757150547517
  551770292443058012639001600
Piecewise
     Transformation
                   as-futures

(defmacro as-futures [[a args] & body]
  (let [parts!          (partition-by #{'=>} body)
        [acts _ [res]] (partition-by #{:as} (first parts))
        [_ _ task]! parts]
    `(let [~res (for [~a ~args] (future ~@acts))]
       ~@task)))
Piecewise
     Transformation
                   as-futures

(defmacro as-futures [[a args] & body]
  (let [parts!          (partition-by #{'=>} body)
        [acts _ [res]] (partition-by #{:as} (first parts))
        [_ _ task]! parts]
    `(let [~res (for [~a ~args] (future ~@acts))]
       ~@task)))
Piecewise
    Transformation
                  as-futures
(defn- extract-results-name [[_ [nom]]]
  (if nom
    nom
    (throw (Exception. "Missing :as clause!"))))

(defmacro as-futures [[a args] & body]
  (let [parts!       (partition-by #{'=>} body)
        [acts & as] (partition-by #{:as} (first parts))
        res          (extract-results-name as)
        [_ _ task]! parts]
    `(let [~res (for [~a ~args] (future ~@acts))]
       ~@task)))
What lies beneath...
Primacy
                                 of
                             Semantics
I also regard syntactical problems as essentially irrelevant to programming languages at their present
     stage ... the urgent task in programming languages is to explore the !eld of semantic possibilities.
           — Christopher Strachey - “Fundamental Concepts in Programming Languages”
A Contract

(defn sqr-contract [f n]
  {:pre [(number? n)]
   :post [(number? %) (pos? %)]}
  (f n))

(defn sqr-actions [n]
  (* n n))

(def sqr (partial sqr-contract sqr-actions))

(sqr :a)
;; AssertionError (number? n)
Piecewise Contracts
   (defn sqr-contract-zero [f n]
     {:pre [(not= 0 n)]}
     (f n))

   (def sqr (partial sqr-contract-zero
                     (partial sqr-contract
                              sqr-actions)))

   (sqr :a)
   ;; AssertionError (number? n)

   (sqr 0)
   ;; AssertionError (not= 0 n)

   (sqr 10)
   ;=> 100
HOF Contracts

 (provide/contracts
  [choose-numbers
   "Contract for a function that chooses
    numbers from a seq based on a pred."
   [f s] [(_ f number? => truthy?)
          (seqable? s)
          =>
          (subset? % s)]])
HOF Contracts

 (provide/contracts
  [choose-numbers
   "Contract for a function that chooses
    numbers from a seq based on a pred."
   [f s] [(_ f number? => truthy?)
          (seqable? s)
          =>
          (subset? % s)]])



           (_ f number? => truthy?)
(set! *assert* false)
Programs
 Writing
Programs
 Writing
Programs
Minderbinder
http://futureboy.us




           (Specification)
Unit Conversion
   (defn meters->feet [m]
     (* 1250/381 m))

   (defn meters->yards [m]
     (/ (meters->feet m) 3))

   (defn meters->inches [m]
     (* 12 (meters->feet m)))

   (meters->feet 10)
   ;=> ~ 32.81

   (meters->yards 10)
   ;=> ~ 10.9

   (meters->inches 10)
   ;=> ~ 393.7
Unit Conversion

    feet→meters
  inches→meters
   yards→meters
Unit Conversion
     centimeters→shackles
  ramsden-chains→fathoms
                feet→meters
              inches→meters
               yards→meters
            feet→kilometers
         yards→centimeters
old-british-fathom →meters
Unit Conversion
       centimeters→shackles
    ramsden-chains→fathoms
                  feet→meters
                inches→meters
                 yards→meters
              feet→kilometers
           yards→centimeters
  old-british-fathom →meters
Unit Conversion
CM->MI
MM->M         centimeters→shackles
 F->IN     ramsden-chains→fathoms
 IN->Y                   feet→meters
 F->M
                       inches→meters
 Y->M
CM->Y                   yards→meters
F->MM                feet→kilometers
M->MM             yards→centimeters
CM->M    old-british-fathom →meters
  F->Y
bit->n                     e
       ib Conversion
     Unitble yt
meCM->MI
                    a b        te
  MM->M
                  g
    ga ramsden-chains→fathomsy
             centimeters→shackles
                e gab
      by m efeet→meters
   F->IN
   IN->Y
          t
          >e- m inches→meters
         - >
       e t- >e yards→meters
   F->M

      t e
   Y->M
     y t              xa
    b c
  CM->Y
                         by
                    feet→kilometers
     o                       te
  F->MM
  M->MM          yards→centimeters
     bit->byte →meters
  CM->M
    F->Y
        old-british-fathom
Boilerplate
Length Specification
                            - NIST Special Publication 330, 2008 Edition
             - Checking the Net Contents of Packaged Goods - NIST 133



  Unit of length
  Base unit: meter
  The meter is the length of the path travelled by
  light in vacuum during a time interval of
  1/299,792,458 of a second.

  1 inch == 0.0254 meters
  1 foot == 12 inches
  1 yard == 3 feet
(   )
Length Specification
                            - NIST Special Publication 330, 2008 Edition
             - Checking the Net Contents of Packaged Goods - NIST 133



  (Unit of length
  [Base unit: meter]
  The meter is the length of the path travelled by
  light in vacuum during a time interval of
  1/299,792,458 of a second.

  [1 inch == 0.0254 meters]
  [1 foot == 12 inches]
  [1 yard == 3 feet])
Primacy
              of
           Syntax
      one could say that all semantics is being represented as syntax
... semantics has vanished entirely to be replaced with pure syntax.
                                 — John Shutt - “Primacy of Syntax”
Length Specification
                            - NIST Special Publication 330, 2008 Edition
             - Checking the Net Contents of Packaged Goods - NIST 133




  (unit-of length meter
  The meter is the length of the path travelled by
  light in vacuum during a time interval of
  1/299,792,458 of a second.

  inch == 0.0254 meter
  foot == 12 inch
  yard == 3 foot)
Primacy
   of
 Data
  Acceptable or not, sir, it is the truth.
  — Data - ST:TNG “Coming of Age”
Length Specification
                            - NIST Special Publication 330, 2008 Edition
             - Checking the Net Contents of Packaged Goods - NIST 133




  (unit-of length meter
   The meter is the length of the path travelled
  by light in vacuum during a time interval of
  1/299,792,458 of a second.

    inch == 0.0254 meter
    foot == 12 inch
    yard == 3 foot )
Length Specification
                            - NIST Special Publication 330, 2008 Edition
             - Checking the Net Contents of Packaged Goods - NIST 133




  (unit-of ‘length ::meter
  “The meter is the length of the path travelled
  by light in vacuum during a time interval of
  1/299,792,458 of a second.”

  ::inch ‘== 0.0254 ::meter
  ::foot ‘== 12 ::inch
  ::yard ‘== 3 ::foot )
7x6
42
From the DSL

(defunits-of length    ::meter
 “The meter is the length of
the path travelled by light in
vacuum during a time interval
of 1/299,792,458 of a second.”

  ::inch 0.0254
  ::foot [12 ::inch]
  ::yard [3 ::foot])
To a map


 {::meter 1,
  ::inch 0.0254,
  ::foot 0.3048,
  ::yard 0.9144}
To another macro
   (defmacro unit-of-length
   [quantity unit]
     `~(*
          (case unit
            ::meter 1
            ::inch 0.0254
            ::foot 0.3048
            ::yard 0.9144)))
To a use

(unit-of-length 1 ::yard)
0.9144
Learn More



•   http://macronomicon.org

•   “One Day Compilers” by Graydon Hoare

•   http://github.com/fogus/trammel

•   http://github.com/fogus/minderbinder

•   "Hygienic macros through explicit renaming" by William Clinger
Questions?
                          •   Thanks to

                              •   Rich Hickey & Clojure/
                                  core

                              •   Jamie Kite

                              •   Clojure/dev

                              •   Relevance

                              •   CAPCLUG

                              •   Manning Publishing

                              •   Wife and kids

http://joyofclojure.com       •   You
         @fogus

Contenu connexe

Tendances

From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFabio Collini
 
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic LabsTypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic LabsAlfonso Peletier
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorFedor Lavrentyev
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldBTI360
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeCory Forsyth
 
The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196Mahmoud Samir Fayed
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Building fast interpreters in Rust
Building fast interpreters in RustBuilding fast interpreters in Rust
Building fast interpreters in RustIngvar Stepanyan
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
About java
About javaAbout java
About javaJay Xu
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6FITC
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation streamRuslan Shevchenko
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBtdc-globalcode
 

Tendances (20)

From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic LabsTypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Building fast interpreters in Rust
Building fast interpreters in RustBuilding fast interpreters in Rust
Building fast interpreters in Rust
 
Academy PRO: ES2015
Academy PRO: ES2015Academy PRO: ES2015
Academy PRO: ES2015
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
About java
About javaAbout java
About java
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6
 
Java VS Python
Java VS PythonJava VS Python
Java VS Python
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
 
Why Learn Python?
Why Learn Python?Why Learn Python?
Why Learn Python?
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
 

En vedette

ClojureScript Anatomy
ClojureScript AnatomyClojureScript Anatomy
ClojureScript AnatomyMike Fogus
 
The Shape of Functional Programming
The Shape of Functional ProgrammingThe Shape of Functional Programming
The Shape of Functional ProgrammingMike Fogus
 
Introduction to Zeder - a production rules toolkit for Clojure
Introduction to Zeder - a production rules toolkit for ClojureIntroduction to Zeder - a production rules toolkit for Clojure
Introduction to Zeder - a production rules toolkit for ClojureMike Fogus
 
Fertile Ground: The Roots of Clojure
Fertile Ground: The Roots of ClojureFertile Ground: The Roots of Clojure
Fertile Ground: The Roots of ClojureMike Fogus
 
The Return of the Living Datalog
The Return of the Living DatalogThe Return of the Living Datalog
The Return of the Living DatalogMike Fogus
 
Good Parts of JavaScript Douglas Crockford
Good Parts of JavaScript Douglas CrockfordGood Parts of JavaScript Douglas Crockford
Good Parts of JavaScript Douglas Crockfordrajivmordani
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in actionCiro Rizzo
 

En vedette (9)

ClojureScript Anatomy
ClojureScript AnatomyClojureScript Anatomy
ClojureScript Anatomy
 
The Shape of Functional Programming
The Shape of Functional ProgrammingThe Shape of Functional Programming
The Shape of Functional Programming
 
Introduction to Zeder - a production rules toolkit for Clojure
Introduction to Zeder - a production rules toolkit for ClojureIntroduction to Zeder - a production rules toolkit for Clojure
Introduction to Zeder - a production rules toolkit for Clojure
 
Fertile Ground: The Roots of Clojure
Fertile Ground: The Roots of ClojureFertile Ground: The Roots of Clojure
Fertile Ground: The Roots of Clojure
 
The Return of the Living Datalog
The Return of the Living DatalogThe Return of the Living Datalog
The Return of the Living Datalog
 
The world fact book 2011
The world fact book 2011The world fact book 2011
The world fact book 2011
 
Confo
ConfoConfo
Confo
 
Good Parts of JavaScript Douglas Crockford
Good Parts of JavaScript Douglas CrockfordGood Parts of JavaScript Douglas Crockford
Good Parts of JavaScript Douglas Crockford
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in action
 

Similaire à The Macronomicon

ECMAScript 6 and beyond
ECMAScript 6 and beyondECMAScript 6 and beyond
ECMAScript 6 and beyondFrancis Johny
 
C++ extension methods
C++ extension methodsC++ extension methods
C++ extension methodsphil_nash
 
C-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression CalculatorC-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression CalculatorNeeraj Kaushik
 
Cs1123 8 functions
Cs1123 8 functionsCs1123 8 functions
Cs1123 8 functionsTAlha MAlik
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++NUST Stuff
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Chapter 7 functions (c)
Chapter 7 functions (c)Chapter 7 functions (c)
Chapter 7 functions (c)hhliu
 
I wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfI wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfrishteygallery
 
User defined functions
User defined functionsUser defined functions
User defined functionsshubham_jangid
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascriptkvangork
 

Similaire à The Macronomicon (20)

ECMAScript 6 and beyond
ECMAScript 6 and beyondECMAScript 6 and beyond
ECMAScript 6 and beyond
 
C++ extension methods
C++ extension methodsC++ extension methods
C++ extension methods
 
C++ aptitude
C++ aptitudeC++ aptitude
C++ aptitude
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
 
C-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression CalculatorC-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression Calculator
 
Lecture04
Lecture04Lecture04
Lecture04
 
Cs1123 8 functions
Cs1123 8 functionsCs1123 8 functions
Cs1123 8 functions
 
functions of C++
functions of C++functions of C++
functions of C++
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
 
Class method
Class methodClass method
Class method
 
03 function overloading
03 function overloading03 function overloading
03 function overloading
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Chapter 7 functions (c)
Chapter 7 functions (c)Chapter 7 functions (c)
Chapter 7 functions (c)
 
Functions12
Functions12Functions12
Functions12
 
Functions123
Functions123 Functions123
Functions123
 
I wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfI wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdf
 
User defined functions
User defined functionsUser defined functions
User defined functions
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 

Dernier

Benefits of Co working & Shared office space in India
Benefits of Co working & Shared office space in IndiaBenefits of Co working & Shared office space in India
Benefits of Co working & Shared office space in IndiaBrantfordIndia
 
Call Girls Dubai O525547819 Favor Dubai Call Girls Agency
Call Girls Dubai O525547819 Favor Dubai Call Girls AgencyCall Girls Dubai O525547819 Favor Dubai Call Girls Agency
Call Girls Dubai O525547819 Favor Dubai Call Girls Agencykojalkojal131
 
The 5 sec rule - Mel Robins (Hindi Summary)
The 5 sec rule - Mel Robins (Hindi Summary)The 5 sec rule - Mel Robins (Hindi Summary)
The 5 sec rule - Mel Robins (Hindi Summary)Shakti Savarn
 
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?Mikko Kangassalo
 
Spiritual Life Quote from Shiva Negi
Spiritual Life Quote from Shiva Negi Spiritual Life Quote from Shiva Negi
Spiritual Life Quote from Shiva Negi OneDay18
 
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...JeylaisaManabat1
 
English basic for beginners Future tenses .pdf
English basic for beginners Future tenses .pdfEnglish basic for beginners Future tenses .pdf
English basic for beginners Future tenses .pdfbromerom1
 
integrity in personal relationship (1).pdf
integrity in personal relationship (1).pdfintegrity in personal relationship (1).pdf
integrity in personal relationship (1).pdfAmitRout25
 
ingrediendts needed in preparing dessert and sweet sauces
ingrediendts needed in preparing dessert and sweet saucesingrediendts needed in preparing dessert and sweet sauces
ingrediendts needed in preparing dessert and sweet saucesJessicaEscao
 

Dernier (9)

Benefits of Co working & Shared office space in India
Benefits of Co working & Shared office space in IndiaBenefits of Co working & Shared office space in India
Benefits of Co working & Shared office space in India
 
Call Girls Dubai O525547819 Favor Dubai Call Girls Agency
Call Girls Dubai O525547819 Favor Dubai Call Girls AgencyCall Girls Dubai O525547819 Favor Dubai Call Girls Agency
Call Girls Dubai O525547819 Favor Dubai Call Girls Agency
 
The 5 sec rule - Mel Robins (Hindi Summary)
The 5 sec rule - Mel Robins (Hindi Summary)The 5 sec rule - Mel Robins (Hindi Summary)
The 5 sec rule - Mel Robins (Hindi Summary)
 
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?
Virtue ethics & Effective Altruism: What can EA learn from virtue ethics?
 
Spiritual Life Quote from Shiva Negi
Spiritual Life Quote from Shiva Negi Spiritual Life Quote from Shiva Negi
Spiritual Life Quote from Shiva Negi
 
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...
Module-2-Lesson-2-COMMUNICATION-AIDS-AND-STRATEGIES-USING-TOOLS-OF-TECHNOLOGY...
 
English basic for beginners Future tenses .pdf
English basic for beginners Future tenses .pdfEnglish basic for beginners Future tenses .pdf
English basic for beginners Future tenses .pdf
 
integrity in personal relationship (1).pdf
integrity in personal relationship (1).pdfintegrity in personal relationship (1).pdf
integrity in personal relationship (1).pdf
 
ingrediendts needed in preparing dessert and sweet sauces
ingrediendts needed in preparing dessert and sweet saucesingrediendts needed in preparing dessert and sweet sauces
ingrediendts needed in preparing dessert and sweet sauces
 

The Macronomicon

  • 1.
  • 2.
  • 3.
  • 4. am s gr g ro in P it r W rams P r og
  • 5. Code generation • XDoclet • XText • Lombock • Velocity, Erb • MDA • Rails • Hacks
  • 6. p
  • 7. p C
  • 8. Many moons ago #define foo "salad int main(int argc, char* argv[]) { printf(foo bar"); return EXIT_SUCCESS; } ; salad bar
  • 9. Many moons ago #define foo "salad int main(int argc, char* argv[]) { printf(foo bar"); return EXIT_SUCCESS; } ; salad bar (foo bar”); ZOMG!
  • 10. Fixed? #define foo "salad” int main(int argc, char* argv[]) { printf(“foo bar"); return EXIT_SUCCESS; } ; foo bar
  • 11. Hating expressions #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x+y, x-y)*5); return EXIT_SUCCESS; } ; ??
  • 12. Hating expressions #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x+y, x-y)*5); return EXIT_SUCCESS; } ; ?? 2*x+y*x+y-4*x-y*x-y*5
  • 13. Hating expressions #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x+y, x-y)*5); return EXIT_SUCCESS; } ; ?? (2*x)+(y*x)+y-(4*x)-(y*x)-(y*5)
  • 14. Hating expressions #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x+y, x-y)*5); return EXIT_SUCCESS; } ; ?? 2*(x+y)*(x+y)-4*(x-y)*(x-y)*5
  • 15. Fixed? #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x+y, x-y)*5); return EXIT_SUCCESS; } ; ?? discr(a,b,c) ((b)*(b)-4*(a)*(c))
  • 16. FX #define discr(a,b,c) b*b-4*a*c int main(int argc, char* argv[]) { int x=1, y=2; printf(2*discr(x-y, x--, x-y)*5); return EXIT_SUCCESS; } ; ?? 2*(x--)*(x--)-4*(x-y)*(x-y)*5
  • 17.
  • 18. l C++
  • 19. Fact! template <int N> struct Factorial { enum { value = N * Factorial<N-1>::value }; }; template <> struct Factorial<1> { enum { value = 1 }; }; // example use int main() { const int fact5 = Factorial<15>::value; std::cout << fact5 << endl; return 0; } // 120
  • 20. Böhm and Jacopini template <> struct AValue<> { enum { value = 42 }; }; values
  • 21. Böhm and Jacopini template <int X, int Y> struct AFunction template <> { struct AValue<> enum { result = X + Y }; { }; enum { value = 42 }; }; AFunction<1, 2>::result values //=> 3 functions
  • 22. Böhm and Jacopini template <int X, int Y> struct AFunction template <> { struct AValue<> enum { result = X + Y }; { }; enum { value = 42 }; }; AFunction<1, 2>::result values //=> 3 functions template <bool cond, class Then, class Else> struct If { typedef Then RET; }; template <class Then, class Else> struct If<false, Then, Else> { typedef Else RET; }; branching
  • 23. Böhm and Jacopini template <int X, int Y> struct AFunction template <> { struct AValue<> enum { result = X + Y }; { }; enum { value = 42 }; }; AFunction<1, 2>::result values //=> 3 functions template <bool cond, class Then, class Else> template <int N> struct If struct Recur { { typedef Then RET; enum { result = N * Recur<N-1>::result }; }; }; template <class Then, class Else> template <> struct If<false, Then, Else> struct Recur<0> { { typedef Else RET; enum { result = 1}; }; }; branching recursion
  • 24. Böhm and Jacopini template <int X, int Y> struct AFunction template <> { struct AValue<> enum { result = X + Y }; { ring }; Tu enum { value = 42 }; }; AFunction<1, 2>::result values //=> 3 ness functions struct If { Com plete template <bool cond, class Then, class Else> template <int N> struct Recur { typedef Then RET; enum { result = N * Recur<N-1>::result }; }; }; template <class Then, class Else> template <> struct If<false, Then, Else> struct Recur<0> { { typedef Else RET; enum { result = 1}; }; }; branching recursion
  • 25. Böhm and Jacopini template <int X, int Y> struct AFunction template <> { struct AValue<> enum { result = X + Y }; { }; enum { value = 42 }; }; AFunction<1, 2>::result values //=> 3 functions template <bool cond, class Then, class Else> template <int N> struct If struct Recur { { typedef Then RET; enum { result = N * Recur<N-1>::result }; }; }; template <class Then, class Else> template <> struct If<false, Then, Else> struct Recur<0> { { typedef Else RET; enum { result = 1}; }; }; branching recursion
  • 26.
  • 28. From this... List.map (fun x -> x+1) [1; 2; 3]
  • 29. To this... List.map (fun x -> x+1) [1; 2; 3] ExApp (loc, ExApp (loc, ExAcc (loc, ExUid (loc, "List"), ExLid (loc, "map")), ExFun (loc, [(PaLid (loc, "x"), None, ExApp (loc, ExApp (loc, ExLid (loc, "+"), ExLid (loc, "x")), ExInt (loc, "1")))])), ExApp (loc, ExApp (loc, ExUid (loc, "::"), ExInt (loc, "1")), ExApp (loc, ExApp (loc, ExUid (loc, "::"), ExInt (loc, "2")), ExApp (loc, ExApp (loc, ExUid (loc, "::"), ExInt (loc, "3")), ExUid (loc, "[]")))))
  • 30. Just this... List.map (fun x -> x+1) [1; 2; 3]
  • 31. Well, this... List.map (fun x -> x+1) [1; 2; 3] <:expr< List.map (fun x -> x+1) [1; 2; 3] >>
  • 32. The expander List.map (fun x -> x+1) [1; 2; 3] <:expr< List.map (fun x -> x+1) [1; 2; 3] >> camlp4::expr
  • 35. Use cases • Creating binding forms • Control !ow • Icing
  • 37. LISP (label eval (lambda (expr binds) (cond ((atom expr) (assoc expr binds)) ((atom (car expr)) (cond ((eq (car expr) (quote quote)) (cadr expr)) ((eq (car expr) (quote atom)) (atom (eval (cadr expr) binds))) ((eq (car expr) (quote eq)) (eq (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote car)) (car (eval (cadr expr) binds))) ((eq (car expr) (quote cdr)) (cdr (eval (cadr expr) binds))) ((eq (car expr) (quote cons)) (cons (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds)) (t (eval (cons (assoc (car expr) binds) (cdr expr)) binds)))) ((eq (caar expr) (quote label)) (eval (cons (caddar expr) (cdr expr)) (cons (list (cadar expr) (car expr)) binds))) ((eq (caar expr) (quote lambda)) (eval (caddar expr) (append (pair (cadar expr) (eval-args (cdr expr) binds)) binds))) (t (assoc expr binds)))))
  • 38. AIM-57 • MACRO De"nitions in LISP • by Timothy Hart • 1963
  • 39. LISP with macros (label eval (lambda (expr binds) (cond ((atom expr) (assoc expr binds)) ((atom (car expr)) (cond ((eq (car expr) (quote quote)) (cadr expr)) ((eq (car expr) (quote atom)) (atom (eval (cadr expr) binds))) ((eq (car expr) (quote eq)) (eq (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote car)) (car (eval (cadr expr) binds))) ((eq (car expr) (quote cdr)) (cdr (eval (cadr expr) binds))) ((eq (car expr) (quote cons)) (cons (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds)) (t (eval (cons (assoc (car expr) binds) (cdr expr)) binds)))) ((eq (caar expr) (quote label)) (eval (cons (caddar expr) (cdr expr)) (cons (list (cadar expr) (car expr)) binds))) ((eq (caar expr) (quote lambda)) (eval (caddar expr) (append (pair (cadar expr) (eval-args (cdr expr) binds)) binds))) ((eq (caar expr) (quote macro)) (cond ((eq (cadar expr) (quote lambda)) (eval (eval (car (cdddar expr)) (cons (list (car (caddar expr)) (cadr expr)) binds)) binds)))))))
  • 40. LISP with macros (label eval (lambda (expr binds) (cond ((atom expr) (assoc expr binds)) ((atom (car expr)) (cond ((eq (car expr) (quote quote)) (cadr expr)) ((eq (car expr) (quote atom)) (atom (eval (cadr expr) binds))) ((eq (car expr) (quote eq)) (eq (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote car)) (car (eval (cadr expr) binds))) ((eq (car expr) (quote cdr)) (cdr (eval (cadr expr) binds))) ((eq (car expr) (quote cons)) (cons (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds)) (t (eval (cons (assoc (car expr) binds) (cdr expr)) binds)))) ((eq (caar expr) (quote label)) (eval (cons (caddar expr) (cdr expr)) (cons (list (cadar expr) (car expr)) binds))) ((eq (caar expr) (quote lambda)) (eval (caddar expr) (append (pair (cadar expr) (eval-args (cdr expr) binds)) binds))) ((eq (caar expr) (quote macro)) (cond ((eq (cadar expr) (quote lambda)) (eval (eval (car (cdddar expr)) (cons (list (car (caddar expr)) (cadr expr)) binds)) binds)))))))
  • 41. LISP with macros (label eval (lambda (expr binds) (cond ((atom expr) (assoc expr binds)) ((atom (car expr)) (cond ((eq (car expr) (quote quote)) (cadr expr)) ((eq (car expr) (quote atom)) (atom (eval (cadr expr) binds))) ((eq (car expr) (quote eq)) (eq (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote car)) (car (eval (cadr expr) binds))) ((eq (car expr) (quote cdr)) (cdr (eval (cadr expr) binds))) ((eq (car expr) (quote cons)) (cons (eval (cadr expr) binds) (eval (caddr expr) binds))) ((eq (car expr) (quote cond)) (eval-cond (cdr expr) binds)) (t (eval (cons (assoc (car expr) binds) (cdr expr)) binds)))) ((eq (caar expr) (quote label)) (eval (cons (caddar expr) (cdr expr)) (cons (list (cadar expr) (car expr)) binds))) ((eq (caar expr) (quote lambda)) (eval (caddar expr) (append (pair (cadar expr) (eval-args (cdr expr) binds)) binds))) ((eq (caar expr) (quote macro)) (cond ((eq (cadar expr) (quote lambda)) (eval (eval (car (cdddar expr)) (cons (list (car (caddar expr)) (cadr expr)) binds)) binds)))))))
  • 42. Lightweight fn/blocks (defmacro when-not def when_not(condition, &blk) yield unless condition control !ow [condition & body] `(when (not ~condition) end ~@body)) when_not(1.even?) { (when-not (even? 1) puts "not even" (println “not even)) } ;; not even ## not even module Enumerable def scope &blk (defmacro scope yield *(self.to_a) [vals names & body] `(let [[~@names] ~vals] bindings end end ~@body)) (0..20).scope { | a, b | (scope (range) [a b] puts "#{a} and #{b}" (println (str a " and " b))) } ;; 0 and 1 ## 0 and 1
  • 43. Baysick object Lunar extends Baysick { def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 130 PRINT "You don't have that much fuel" 140 GOTO 100 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast (" % 'v % ")km/s" 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" 250 END RUN } }
  • 44. Symbol Baysick Symbol object Lunar extends Baysick { def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) Symbol 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." Symbol 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 Symbol 130 PRINT "You don't have that much fuel" 140 GOTO 100 Symbol 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast (" % 'v % ")km/s" 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" 250 END RUN } }
  • 45. Symbol Baysick Symbol object Lunar extends Baysick { def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) Symbol 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." Symbol 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 Symbol 130 PRINT "You don't have that much fuel" 140 GOTO 100 Symbol 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" Implicit Implicit Implicit 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast ("Implicit% ")km/s" % 'v 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" Implicit Implicit 250 END RUN } } Implicit
  • 46. Symbol Baysick Symbol object Lunar extends Baysick { def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) Symbol 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." Symbol 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 Symbol 130 PRINT "You don't have that much fuel" 140 GOTO 100 Symbol 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) Closure 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" Implicit Implicit Implicit 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast ("Implicit% ")km/s" % 'v 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" Implicit Implicit Closure 250 END RUN } } Implicit
  • 47. Map lookup Map lookup Symbol Baysick Symbol object Lunar extends Baysick { Map lookup def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) Symbol 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." Symbol 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 Symbol 130 PRINT "You don't have that much fuel" 140 GOTO 100 Symbol 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) Closure 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" Implicit Implicit Implicit 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast ("Implicit% ")km/s" % 'v 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" Implicit Implicit Closure 250 END RUN } } Implicit
  • 48. Map lookup Map lookup Symbol Baysick Symbol object Lunar extends Baysick { Map lookup def main(args:Array[String]) = { 20 LET ('dist := 100) 30 LET ('v := 1) Symbol 40 LET ('fuel := 1000) 50 LET ('mass := 1000) 60 PRINT "You are a in control of a lunar lander, drifting towards the moon." 80 PRINT "Each turn you must decide how much fuel to burn." Symbol 90 PRINT "To accelerate enter a positive number, to decelerate a negative" 100 PRINT "Dist " % 'dist % "km, " % "Vel " % 'v % "km/s, " % "Fuel " % 'fuel 110 INPUT 'burn 120 IF ABS('burn) <= 'fuel THEN 150 Symbol 130 PRINT "You don't have that much fuel" 140 GOTO 100 Symbol 150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass)) Closure 160 LET ('fuel := 'fuel - ABS('burn)) 170 LET ('dist := 'dist - 'v) 180 IF 'dist > 0 THEN 100 190 PRINT "You have hit the surface" Implicit Implicit Implicit 200 IF 'v < 3 THEN 240 210 PRINT "Hit surface too fast ("Implicit% ")km/s" % 'v 220 PRINT "You Crashed!" 230 GOTO 250 240 PRINT "Well done!" Implicit Implicit Closure 250 END RUN } } TRAMPOLINE!!! Implicit
  • 49. Mapping Dilemma One of the issues here is actually encapsulation: without macros, the ability to create abstractions is limited by the degree to which underlying language constructs peek through the abstraction barrier.
  • 50. Use cases • Creating binding forms • Control !ow • Icing
  • 51. “All legitimate uses of macros are legitimate” — Yogi Berra
  • 52. Use cases • Creating binding forms • Control !ow • Abstraction • Transformation (Houdini, boilerplate) • Optimization • True power awesomeness • Icing
  • 53. Think
  • 54. What do you want? • A way to de"ne local bindings • Properly scoped
  • 55. Do you need a macro? (defn build-memoizer ([cache-factory f & args] (let [cache (atom (apply cache-factory f args))] (with-meta (fn [& args] (let [cs (swap! cache through f args)] @(fogus.clache/lookup cs args))) {:unk cache :unk-orig f})))) ;; usage (defn memo ([f] (memo f {})) ([f seed] (build-memoizer basic-cache-factory f seed)))
  • 56. What does it look like? (LET ([rise 1] [run 2]) (/ rise run)) ;=> 1/2
  • 57. What is it really? ((fn [rise] ((fn [run] (/ rise run)) 2)) 1) ;=> 1/2
  • 58. Type (defn foldr [f acc [h & t]] (if h (f h (foldr f acc t)) acc)) (defmacro LET [bindings & body] (foldr (fn [[n v] subexpr] `((fn [~n] ~subexpr) ~v)) `(do ~@body) bindings))
  • 59. Quick Tip: binding idiom (defmacro LET* [bindings & body] (assert (vector? bindings)) (foldr (fn [[n v] subexpr] `((fn [~n] ~subexpr) ~v)) `(do ~@body) (partition 2 bindings))) (LET [rise 1 run 2] (/ rise run)) ;=> 1/2
  • 61. Hygiene An hygienic macro is one where the meanings of symbols that aren't parameters to the macro are bound at the de!nition site rather than the expansion site. — James Iry @ Lambda the Ultimate
  • 62. Degenerative Case 1 (defmacro tis-true? [a] `(when a :twas-true)) ;; somewhere (def a false) ;; somewhere else (tis-true? true) ;=> nil
  • 63. Degenerative Case 1 (when my-ns/a :twas-true)
  • 64. Degenerative Case 1 (defmacro tis-true? [a] `(when ~a :twas-true)) (tis-true? true) ;=> :twas-true
  • 65. vs.
  • 66. Degenerative Case 2 (defmacro awhen [condition & body] `(if-let [~'it ~condition] ~@body)) (awhen (:a {:a 42}) (println it)) ; 42
  • 67. Degenerative Case 2 (defmacro awhen [condition & body] `(if-let [~'it ~condition] ~@body)) (awhen (:a {:a 42}) (println it)) ; 42
  • 68. Degenerative Case 2 (def it :not-it) (awhen (:a {:a 42}) (println it)) ; 42
  • 69. Better (def it :not-it) (when-let [it (:a {:a 42})] (println it)) ; 42
  • 71. Use
  • 74. MSL Mood-speci"c Languages -- Ian Piumarta
  • 76. Step 0: What did I want? • Goals • New :pre/:post syntax • Decomplected contracts • Invariants on records, types, references • Better error reporting • Misc.
  • 77. Step 1: Did I need a macro? Yes.
  • 78. Step 1: Did I need a macro? Yes.
  • 79.
  • 80. Second-class Forms
  • 81. Macros are first-class at making second-class forms (defrecord Date [year month day]) (defn Date? [d] (= klass (type d))) (defn new-Date [& {:or {year 1970, month 1, day 1}, :as m, :keys [year month day]}] {:pre [(every? number? [year month day]) (< month 13) (> month 0) (< day 32) (> day 0)]} (-> (Date. 1970 1 1) (merge m)))
  • 83. Trammel is... New :pre/:post Syntax (defconstrainedfn sqr [n],[number? (not= 0 n) => pos? number?] (* n n))
  • 84. Trammel is... Decomplected Contracts (defn gregorian-last-day-of-month ([d] (gregorian-last-day-of-month (:month d) (:year d))) ([month year] (if (and (= month 2) (leap-year? year)) 29 (nth *canonical-days* (dec month))))) (provide/contracts [gregorian-last-day-of-month "Gregorian last day calculation constraints" [d] [Date? :month :year => number? pos?] [m y] [all-positive? => number? pos?]])
  • 85. Trammel is... Record Invariants (defconstrainedrecord Date [year 1970 month 1 day 1] [(every? number? [year month day]) (< month 13) (> month 0) (< day 32) (> day 0)]) (new-Date :month 11 :day 12 :year “AD”) ;; Assert failed: (every? number? [year month day])
  • 86. Trammel is... Better Error Reporting (sqr 10) ;=> 100 (sqr :a) ; Pre-condition Error: (pos? :a) (sqr 0) ; Post-condition Error: (pos? 0)
  • 88. Piecewise Transformation (defmacro defconstrainedfn [name & body] (let [mdata (if (string? (first body)) {:doc (first body)} {}) body (if (:doc mdata) (next body) body) body (if (vector? (first body)) (list body) body) body (for [[args cnstr & bd] body] (list* args (if (vector? cnstr) (second (build-cnstr-map args cnstr)) cnstr) bd))] `(defn ~name ~(str (:doc mdata)) ~@body)))
  • 89. Piecewise Transformation (defmacro defmulti [mm-name & options] (let [docstring (if (string? (first options)) (first options) nil) options (if (string? (first options)) (next options) options) m (if (map? (first options)) (first options) {}) options (if (map? (first options)) (next options) options) dispatch-fn (first options) options (next options) m (if docstring (assoc m :doc docstring) m) ...)
  • 90. Piecewise Transformation as-futures (as-futures [<arg-name> <all-args>] <actions-using-arg-name> :as <results-name> => <actions-using-results>)
  • 91. Piecewise Transformation as-futures (defn sum-facts [& ns] (as-futures [n ns] (reduce * (range 1 n)) :as results => (reduce #(+ % (deref %2)) 0 results))) (sum-facts 100 13 123 56 33) ;=> 98750442008336013624115798714482080125644041 37071685821402414202949370696061281065394095 61103888585087569526895318024046688120956989 53738011044836999122093443893501757150547517 551770292443058012639001600
  • 92. Piecewise Transformation as-futures (defmacro as-futures [[a args] & body] (let [parts! (partition-by #{'=>} body) [acts _ [res]] (partition-by #{:as} (first parts)) [_ _ task]! parts] `(let [~res (for [~a ~args] (future ~@acts))] ~@task)))
  • 93. Piecewise Transformation as-futures (defmacro as-futures [[a args] & body] (let [parts! (partition-by #{'=>} body) [acts _ [res]] (partition-by #{:as} (first parts)) [_ _ task]! parts] `(let [~res (for [~a ~args] (future ~@acts))] ~@task)))
  • 94. Piecewise Transformation as-futures (defn- extract-results-name [[_ [nom]]] (if nom nom (throw (Exception. "Missing :as clause!")))) (defmacro as-futures [[a args] & body] (let [parts! (partition-by #{'=>} body) [acts & as] (partition-by #{:as} (first parts)) res (extract-results-name as) [_ _ task]! parts] `(let [~res (for [~a ~args] (future ~@acts))] ~@task)))
  • 96. Primacy of Semantics I also regard syntactical problems as essentially irrelevant to programming languages at their present stage ... the urgent task in programming languages is to explore the !eld of semantic possibilities. — Christopher Strachey - “Fundamental Concepts in Programming Languages”
  • 97. A Contract (defn sqr-contract [f n] {:pre [(number? n)] :post [(number? %) (pos? %)]} (f n)) (defn sqr-actions [n] (* n n)) (def sqr (partial sqr-contract sqr-actions)) (sqr :a) ;; AssertionError (number? n)
  • 98. Piecewise Contracts (defn sqr-contract-zero [f n] {:pre [(not= 0 n)]} (f n)) (def sqr (partial sqr-contract-zero (partial sqr-contract sqr-actions))) (sqr :a) ;; AssertionError (number? n) (sqr 0) ;; AssertionError (not= 0 n) (sqr 10) ;=> 100
  • 99. HOF Contracts (provide/contracts [choose-numbers "Contract for a function that chooses numbers from a seq based on a pred." [f s] [(_ f number? => truthy?) (seqable? s) => (subset? % s)]])
  • 100. HOF Contracts (provide/contracts [choose-numbers "Contract for a function that chooses numbers from a seq based on a pred." [f s] [(_ f number? => truthy?) (seqable? s) => (subset? % s)]]) (_ f number? => truthy?)
  • 102.
  • 105. http://futureboy.us (Specification)
  • 106.
  • 107. Unit Conversion (defn meters->feet [m] (* 1250/381 m)) (defn meters->yards [m] (/ (meters->feet m) 3)) (defn meters->inches [m] (* 12 (meters->feet m))) (meters->feet 10) ;=> ~ 32.81 (meters->yards 10) ;=> ~ 10.9 (meters->inches 10) ;=> ~ 393.7
  • 108. Unit Conversion feet→meters inches→meters yards→meters
  • 109. Unit Conversion centimeters→shackles ramsden-chains→fathoms feet→meters inches→meters yards→meters feet→kilometers yards→centimeters old-british-fathom →meters
  • 110. Unit Conversion centimeters→shackles ramsden-chains→fathoms feet→meters inches→meters yards→meters feet→kilometers yards→centimeters old-british-fathom →meters
  • 111. Unit Conversion CM->MI MM->M centimeters→shackles F->IN ramsden-chains→fathoms IN->Y feet→meters F->M inches→meters Y->M CM->Y yards→meters F->MM feet→kilometers M->MM yards→centimeters CM->M old-british-fathom →meters F->Y
  • 112. bit->n e ib Conversion Unitble yt meCM->MI a b te MM->M g ga ramsden-chains→fathomsy centimeters→shackles e gab by m efeet→meters F->IN IN->Y t >e- m inches→meters - > e t- >e yards→meters F->M t e Y->M y t xa b c CM->Y by feet→kilometers o te F->MM M->MM yards→centimeters bit->byte →meters CM->M F->Y old-british-fathom
  • 113.
  • 115. Length Specification - NIST Special Publication 330, 2008 Edition - Checking the Net Contents of Packaged Goods - NIST 133 Unit of length Base unit: meter The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second. 1 inch == 0.0254 meters 1 foot == 12 inches 1 yard == 3 feet
  • 116. ( )
  • 117. Length Specification - NIST Special Publication 330, 2008 Edition - Checking the Net Contents of Packaged Goods - NIST 133 (Unit of length [Base unit: meter] The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second. [1 inch == 0.0254 meters] [1 foot == 12 inches] [1 yard == 3 feet])
  • 118. Primacy of Syntax one could say that all semantics is being represented as syntax ... semantics has vanished entirely to be replaced with pure syntax. — John Shutt - “Primacy of Syntax”
  • 119. Length Specification - NIST Special Publication 330, 2008 Edition - Checking the Net Contents of Packaged Goods - NIST 133 (unit-of length meter The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second. inch == 0.0254 meter foot == 12 inch yard == 3 foot)
  • 120. Primacy of Data Acceptable or not, sir, it is the truth. — Data - ST:TNG “Coming of Age”
  • 121. Length Specification - NIST Special Publication 330, 2008 Edition - Checking the Net Contents of Packaged Goods - NIST 133 (unit-of length meter The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second. inch == 0.0254 meter foot == 12 inch yard == 3 foot )
  • 122. Length Specification - NIST Special Publication 330, 2008 Edition - Checking the Net Contents of Packaged Goods - NIST 133 (unit-of ‘length ::meter “The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second.” ::inch ‘== 0.0254 ::meter ::foot ‘== 12 ::inch ::yard ‘== 3 ::foot )
  • 123. 7x6
  • 124. 42
  • 125. From the DSL (defunits-of length ::meter “The meter is the length of the path travelled by light in vacuum during a time interval of 1/299,792,458 of a second.” ::inch 0.0254 ::foot [12 ::inch] ::yard [3 ::foot])
  • 126. To a map {::meter 1, ::inch 0.0254, ::foot 0.3048, ::yard 0.9144}
  • 127. To another macro (defmacro unit-of-length [quantity unit] `~(* (case unit ::meter 1 ::inch 0.0254 ::foot 0.3048 ::yard 0.9144)))
  • 129. 0.9144
  • 130. Learn More • http://macronomicon.org • “One Day Compilers” by Graydon Hoare • http://github.com/fogus/trammel • http://github.com/fogus/minderbinder • "Hygienic macros through explicit renaming" by William Clinger
  • 131. Questions? • Thanks to • Rich Hickey & Clojure/ core • Jamie Kite • Clojure/dev • Relevance • CAPCLUG • Manning Publishing • Wife and kids http://joyofclojure.com • You @fogus