scheme – Parerga und Paralipomena http://www.michelepasin.org/blog At the core of all well-founded belief lies belief that is unfounded - Wittgenstein Sat, 29 Jan 2011 23:00:15 +0000 en-US hourly 1 https://wordpress.org/?v=5.2.11 13825966 Opening a Finder’s window from Impromptu (alas how to use the applescript bridge..) http://www.michelepasin.org/blog/2011/01/30/opening-a-finders-window-from-impromptu-alas-how-to-use-the-applescript-bridge/ Sat, 29 Jan 2011 23:00:15 +0000 http://www.michelepasin.org/blog/?p=982 Imagine you’ve got a bunch of audio samples you want to load up while livecoding with Impromptu but you can’t remember exactly their names – it’d be handy to be able to open up the corresponding Finder window directly from scheme, without too much clicking around. Do-able or not?

I spent some time trying to figure this out, and the answer is yes! Quite a nice learning experience… although it came with a surprise at the end.

Originally I thought, let’s do it via impromptu’s ObjC bridge. I don’t know much about ObjC but after a bit of googling it seemed evident that the quickest way to accomplish this is by writing ObjC code that, in turns, runs a simple applescript command that opens a window:

 

NSString *s = [NSString stringWithFormat:
     @"tell application "Terminal" to do script "cd %@"", folderPath];

NSAppleScript *as = [[NSAppleScript alloc] initWithSource: s];
[as executeAndReturnError:nil];

 

So I translated the bottom part of the code above into impromptu/scheme:

 

(define run_applescript
   (lambda (script)
      (objc:call (objc:call (objc:call "NSAppleScript" "alloc")
                            "initWithSource:"
                            script)
                 "executeAndReturnError:" )))

 

That is a generic script-running function, that is, you can pass any script and it’ll run it, eg:

 

(define script0 "
   tell application "Finder" to open folder "Macintosh HD:Users"
   tell application "Finder" to activate"
)

(define script1 "
   tell application "Terminal" to do script "cd ~; open .""
)

(define script2 "
                tell application "System Events"n
                tell dock preferencesn
                set properties to {autohide:false}n
                end telln
                end tell"
)

;; finally, let’s choose randomly one of the scripts above and run it
(run_applescript (random ‘(script0 script1 script2)))

 

Now, back to the original problem: in order to open a Finder’s window at a specified location we need to pass the location variable to our function run_applescript; also, we want to be able to pass unix path expressions (eg ‘/Users/mike/music/’), so we’ve got to transform that path syntax into the semicolon-delimited macintosh syntax (“Macintosh HD:Users:mike:music”) needed by the applescript function we’re using. That’s easily done with string-replace, so here we go:

 

(define open_finder_at
   (lambda (location)
      (let* ((llocation (stringreplace location "/" ":"))
              (script (string-append "tell application "Finder" to activate open folder "Macintosh HD" llocation """)))
         (objc:call (objc:call (objc:call "NSAppleScript" "alloc")
                               "initWithSource:"
                               script)
                    "executeAndReturnError:" ))))

(open_finder_at "/Users/me/")

 

That’s pretty much it really… now we can easily open OsX Finder’s windows from within Impromptu.

But as I said above, there’s a surprise: after getting this far I thought I’d search impromptu’s mailing list for more examples of obj:call …. and guess what, there’s already a system function that runs applescripts, it’s called sys:run-applescript !

Too bad, it’s been a rewarding learning experience anyways…

 

]]>
2188
Scheme and Lisp http://www.michelepasin.org/blog/2010/11/08/scheme-and-lisp/ Mon, 08 Nov 2010 12:57:13 +0000 http://www.michelepasin.org/blog/?p=866 If you’re coming from Lisp, and then start using Scheme (or the other way around) there are a few small differences between the two languages that it’s useful to always keep in mind. I tried to do that a number of times, but inevitably I find myself once again wondering: how do you say ‘progn’ in scheme?

So, since I recently found online a succinct table that sums up the differences, I thought I’d pass it on to posterity here too.

Screen shot 2010-11-08 at 14.29.12.png

By the way, on the same site the authors report of a small scheme library (initdr.scm) that implements a few very common Lisp functions. Including [dotimes dolist intersection, union set-difference copy-list subset every some copy-tree subst sublis nconc nreverse]… Quite useful too!

UPDATE 28/11/10:

I realized that most of these lisp functions are already available in Impromptu, under the cl: namespace (check out the common-lisp library functions section on the wiki). Below are just a couple of additions to that, based on the initdr.scm library I was mentioning.. apologies for the confusion!

;;;;;;;;;;;;;;;;
;;; LISP ADDITIONS 
;; the rest of this is in the cl: impromptu library
;;;;;;;;;;;;;;;;


(define cl:first car)
(define cl:rest cdr)
(define cl:count length)

;; reverse of cons: (cons 'b '(a))
(define cl:l-put
   (lambda (obj lst)
      (reverse (cons obj (reverse lst)))))

;; dont know why but I like it reversed..
(define cl:nth (lambda (x lst)
               (list-ref lst x)))


(define (1+ n) (+ n 1))
(define (1- n) (- n 1))


;; (subst 9 7 '(5 (5 6 7(6 7))))    =>  (5 (5 6 9 (6 9)))      
(define (cl:subst new old tree)
  (if (pair? tree)
      (let ((left (subst new old (car tree)))
            (right (subst new old (cdr tree))))
        (if (and (eq? left (car tree))
                 (eq? right (cdr tree)))
            tree
            (cons left right)))
      (if (eqv? old tree)
          new
          tree)))



;; (sublis '((6 . 9) (7 . 10)) '(5 (5 6 7 (6 7)))))  => (5 (5 9 10 (9 10)))
(define (cl:sublis alist tree)
  (if (pair? tree)
      (let ((left (sublis alist (car tree)))
            (right (sublis alist (cdr tree))))
        (if (and (eq? left (car tree))
                 (eq? right (cdr tree)))
            tree
            (cons left right)))
      (let ((new (assv tree alist)))
        (if new
            (cdr new)
            tree) ) ) )


;; (copy-tree '(5 (5 6 7(6 7))))
(define (cl:copy-tree x)
  (if (pair? x)
      (cons (copy-tree (car x))
            (copy-tree (cdr x)))
      x))


; Convert a floating-point number to a string of sign and at most 4 characters.
; Rounds the number so that 1.999 will come out as 2.00 , very small as 0.0 .
; numstring is written assuming that num is not too large or too small,
; i.e. num must be printable in 4 digits.
(define (cl:numstring num)
  (let* ((numc (abs num)) (sign (if (< num 0) -1 1)) (exponent 0))
    (if (< numc 1.0e-6)
    "0.0"
    (begin
      (if (< numc 1.0)
          (begin (while (< numc 100)
                (set! numc (* numc 10))
                (set! exponent (1- exponent)))
             (set! numc (* (round numc) (expt 10 exponent))) )
          (set! numc (* numc 1.0001)))
      (if (< sign 0)
          (string-append "-"
                 (substring (number->string numc) 0
                   (min 4 (string-length (number->string numc)))))
          (substring (number->string numc) 0
             (min 4 (string-length (number->string numc))))) ) ) ))




;(list-flatten '(9 9 (9 9 9 ))))  = (9 9 9 9 9)

(define cl:list-flatten 
   (lambda (l)
      (cond ((null? l)
             '())
            ((atom? l)
             (list l))
            (#t (append (cl:list-flatten  (car l)) (cl:list-flatten  (cdr l)))))))
]]>
866
A video that may convince you that LISPers are a bit crazy http://www.michelepasin.org/blog/2010/10/29/a-video-that-may-convince-you-that-lispers-are-a-bit-crazy/ Fri, 29 Oct 2010 14:25:26 +0000 http://www.michelepasin.org/blog/?p=860 Actually it’s not just a video, there’s a book too:

Land of Lisp, Learn to Program in Lisp, One Game at a Time! by Conrad Barski, M.D.

]]>
860
Learning resources about Scheme http://www.michelepasin.org/blog/2010/08/10/learning-resources-about-scheme/ Tue, 10 Aug 2010 17:27:17 +0000 http://www.michelepasin.org/blog/?p=808 3eangz5w.jpg

So you’ve decided to know everything about scheme and rock the world using fast-paced programming environments like Impromptu.
Well, I confess I did think that on several occasions, but still I haven’t made it even half way through the schemer pilgmim’s path. But I’ve collected quite a few useful resources in the process, and those I can certainly share!

So in what follows I’ve put together a list of learning resources about Scheme that I found useful.. First off, two links that might be useful in all situations:

  • Little Scheme, an online interpreter that you can use for testing things out while you’re on holidays
  • Schemers.org, semi-official website containing news and lots of links to other resources
  • Now, why don’t we start with the definition offered by the self-regulating wikipedia collective intelligence? Here we go:

    Scheme is one of the two main dialects of the programming language Lisp. Unlike Common Lisp, the other main dialect, Scheme follows a minimalist design philosophy specifying a small standard core with powerful tools for language extension. Its compactness and elegance have made it popular with educators, language designers, programmers, implementors, and hobbyists, and this diverse appeal is seen as both a strength and, because of the diversity of its constituencies and the wide divergence between implementations, one of its weaknesses

    If this blurb hasn’t made you proud of learning such a slick language, you’ll surely find more interesting ideas in what follows. I divided up the list in two sections, generic learning materials about scheme, and tutorials about specific topics (for now, only macros are included).
    ———————————-

    1. Learning Resources About Scheme:

  • Scheme for Common Lispers, article

    The Scheme dialect of Lisp was created in 1975 by Guy Steele and Gerry Sussman to explore ideas in programming-language semantics. They showed that a powerful language can be made “not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary”. Scheme pioneered lexical scope in Lisp, first-class continuations, and tail recursion, and more recently added an advanced macro system. It’s the best-known Lisp dialect after Common Lisp (which it influenced).
    This note summarizes the differences from CL that might slow down a CL programmer trying to read a Scheme program; people without a CL background, or wanting to write programs of their own, should see the references.

  • the Schematics Scheme Cookbook

    The Schematics Scheme Cookbook is a collaborative effort to produce documentation and recipes for using Scheme for common tasks. See the BookIntroduction for more information on the Cookbook’s goals, and the important ContributorAgreement statement.

  • Harvey, Wright, Simply Scheme: Introducing Computer Science, 1999 MIT press [a classic]

    Symbolic programming is one aspect of the reason why we like to teach computer science using Scheme instead of a more traditional language. More generally, Lisp (and therefore Scheme) was designed to support what we’ve called the radical view of computer science. In this view, computer science is about tools for expressing ideas. Symbolic programming allows the computer to express ideas; other aspects of Lisp’s design help the programmer express ideas conveniently. Sometimes that goal comes in conflict with the conservative computer scientist’s goal of protection against errors.

  • Felleisen, Findler, Flatt, Krishnamurthi, How to Design Programs An Introduction to Computing and Programming, MIT 2001

    [..] programming is more than just a vocational skill. Indeed, good programming is a fun activity, a creative outlet, and a way to express abstract ideas in a tangible form. And designing programs teaches a variety of skills that are important in all kinds of professions: critical reading, analytical thinking, creative synthesis, and attention to detail.
    We therefore believe that the study of program design deserves the same central role in general education as mathematics and English. Or, put more succinctly, everyone should learn how to design programs.
    On one hand, program design teaches the same analytical skills as mathematics. But, unlike mathematics, working with programs is an active approach to learning. Interacting with software provides immediate feedback and thus leads to exploration, experimentation, and self-evaluation. Furthermore, designing programs produces useful and fun things, which vastly increases the sense of accomplishment when compared to drill exercises in mathematics. On the other hand, program design teaches the same analytical reading and writing skills as English. Even the smallest programming tasks are formulated as word problems. Without critical reading skills, a student cannot design programs that match the specification. Conversely, good program design methods force a student to articulate thoughts about programs in proper English.

  • Dybvig, The Scheme Programming Language, 2003MIT press

    This book is intended to provide an introduction to the Scheme programming language but not an introduction to programming in general. The reader is expected to have had some experience programming and to be familiar with terms commonly associated with computers and programming languages. The author recommends that readers unfamiliar with Scheme or Lisp also read The Little Schemer [see below]to become familiar with the concepts of list processing and recursion. Readers new to programming should begin with an introductory text on programming.

  • Nils M Holm, “Sketchy LISP” [you can download the book here Update 08/12: this book has become ‘Sketchy Scheme’ and is now for-sale here]

    Sketchy LISP is a step-by-step introduction to functional programming in Scheme. It covers various aspects of the language including data types, conditional evaluation, list processing, lexical scoping, closures, recursion, dynamic typing, etc. By means of numerous examples of varying complexity, it takes the reader on an entertaining and informative tour through the language.
    The Scheme language achieves what only few languages have managed before: to bring fun back to programming. Its simple syntax, clean semantics, and powerful functions open the door to a fresh perspective on program design. Programming in Scheme is fun, and this book is an attempt to share some of that fun.

  • Friedman and Felleisen, The Little Schemer, 1996 MIT press

    The goal of this book is to teach the reader to think recursively. Our first task, therefore, is to decide which language to use to communicate this concept. There are three obvious choices: a natural language, such as English; formal mathematics; or a programming language. Natural languages are ambiguous, imprecise, and sometimes awkwardly verbose. These are all virtues for general communication, but something of a drawback for communicating concisely as precise a concept as the power of recursion. The language of mathematics is the opposite of natural language: it can express powerful formal ideas with only a few symbols. We could, for example, describe the entire technical content of this book in less than a page of mathematics, but the reader who understands that page has little need for this book. For most people, formal mathematics is not very intuitive. The marriage of technology and mathematics presents us with a third, almost ideal choice: a programming language. Programming languages are perhaps the best way to convey the concept of recursion. They share with mathematics the ability to give a formal meaning to a set of symbols. But unlike mathematics, programming languages can be directly experienced—you can take the programs in this book and try them, observe their behavior, modify them, and experience the effect of your modifications.

  • The Weiner Lectures Archives [various videos, but not complete lectures unfortunately]

    The goal of this project is to make knowledge of computer science easily available not only to the students at Berkeley, but also to the entire community. For several years, faculty members have been videotaping lectures in CS large lower division courses, mainly as an aid to students with time conflicts that prevent them from attending lectures. By hosting an archive storing all CS lectures that were recorded, we hope the computing knowledge that has been gathered can be easily shared. As a teaching aid, a ‘greatest hits’ lecture will also be compiled for each course covering all major topics addressed in the corresponding class. The best parts of many different past lectures will be linked together and presented along with slides to make this greatest hits lecture. This lecture should represent the best teaching abilities in the lower division CS lectures and should be a valuable resource in the computer community for basic CS knowledge. Thanks to the generous donation of Larry Weiner this online site should become a permanent resource.

  • ———————-

    2. Specific topics:

    On Macros and metaprogramming:

  • The art of metaprogramming, Part 1: Introduction to metaprogramming, IBM developer works

    Summary: One of the most under-used programming techniques is writing programs that generate programs or program parts. Learn why metaprogramming is necessary and look at some of the components of metaprogramming (textual macro languages, specialized code generators). See how to build a code generator and get a closer look at language-sensitive macro programming in Scheme.

  • Lisp Macros — How to Define Entirely New Languages in Lisp

    This is a very interesting lesson if you want to deeply understand Lisp, and some very deep things about programming, but it’s also entirely optional; We suggest that you do through it, but not worry too much about understanding it in detail. If you get very deeply into programming, you’ll find that Lisp macros are an amazing tool, but they are also somewhat mind-bending, and used rather rarely in simple programming. So, feel free to skip this lesson, or at least, if you do study it, let it flow over you, and maybe come back to it later on if you find yourself wanting to know more about some of the deep and subtle reaches of Lisp programming.

  • Scheme FAQ Macros, on schemewiki.org
  • Sources for learning about Scheme Macros: define-syntax and syntax-rules, a thread on StackOverflow
  • A scheme syntax rules primer, an interesting blog post
  • ———————-

    That’s all for now… I’ll be adding more stuff as I run into it!

    ]]>
    808
    Impromptu: access the Wiki docs from the editor http://www.michelepasin.org/blog/2010/02/15/impromptu-function-to-access-wiki-docs-from-the-editor/ Mon, 15 Feb 2010 05:31:34 +0000 http://magicrebirth.wordpress.com/?p=559
    >>>
    When you’re Impromptu-ing but don’t know the meaning or syntax of a function, the usual thing to do is calling (help function-name) to get some help about that function, or (help function-name #t) if you want to see also the examples associated with it. The help text gets displayed in the log view, so that you can then copy/paste what you need from there.
    Quite useful, but nonetheless I always find myself fighting with the log window: too small, hidden away by other canvases, or not readable anymore cause after calling the help function I’ve evaluated other stuff that has moved up the much needed help-text.

    Since a couple of months ago Impromptu has a wiki too – so I thought, it’d be nice to see a function’s help in a browser window, and possibly contribute to its explanation too..

    So, that’s the rationale for this little script. By calling ‘wiki’ you can open up a web browser at the relevant Impromptu-wiki page.. as simple as that.

    >>>

    First off, we need a couple of utility functions that are not included in Impromptu by default, for better manipulating strings, lists and webpages (UPDATE 9-Nov2010: some of this symbols have been included in Improptu 2.5, so I prefixed the one below with the utils: namespace):

    ;;;;;;;
    ;; utilities
    ;;;;;;;
    
    ;; (utils:list-flatten '(9 9 (9 9 9 ))))  = (9 9 9 9 9)
    (define utils:list-flatten
       (lambda (l)
          (cond ((null? l)
                 '())
                ((atom? l)
                 (list l))
                (#t (append (utils:list-flatten  (car l)) (utils:list-flatten  (cdr l)))))))
    
    ;; returns a char from a string of length 1, or a list of chars from a longer string
    (define utils:char
       (lambda (string_char)
          (if (string? string_char)
              (if (> (string-length string_char) 0)
                  (if (> (string-length string_char) 1)
                      (string->list string_char)
                      (car (string->list string_char))))
              (print 'please 'enter 'a 'string))))
    
    ;; matches a single character in a string, and replaces it
    (define utils:string-replace
       (lambda (s match replacement)
          (let ((ll (string->list s))
                (match1 (utils:char match))
                (replacement1 (utils:char replacement)))
             (if (= (string-length match) 1)
                 (let ((z (map (lambda (x)
                                  (if (equal? x match1)
                                      replacement1
                                      x))
                               ll)))
                    (list->string (utils:list-flatten z)))
                    ;z)
                 (print "i can match only single characters for now")))))
    
    ;; makes a string upper case
    (define utils:string-capitalize
       (lambda (s)
          (string-append (string (char-upcase (string-ref s 0))) (substring s 1 (string-length s)))))
    
    ;; open-url: calls the default mac browser with a url argument 
    ;; disclaimer: I'm not an objc programmer... found an example at 
    ;; http://macosx.com/forums/software-programming-web-scripting/18422-how-do-i-launch-url-using-cocoa-objective-c.html
    (define utils:open-url
       (lambda (urlstring)
          (let ((urlobj (objc:call "NSURL" "URLWithString:" urlstring))
                (workspace (objc:call "NSWorkspace" "sharedWorkspace")))
             (objc:call workspace "openURL:" urlobj))))
    
     

    >>>
    Finally, the functions for opening the wiki page:

    ;;;;;;;;;;
    ;; wiki url caller
    ;; e.g. (wiki objc:from-address) => goes to http://moso.com.au/wiki/index.php?title=Objc:from-address
    ;;;;;;;;;;
    
    ;; wiki-escape: composes the url so that it matches the ones of the online wiki 
    (define wikiescape
       (lambda (funname)
          (for-each (lambda (x)
                       (set! funname (utils:string-replace funname (car x) (cadr x))))
                    '(("+" "%2B")
                      ("=" "%3D")
                      ("<" "lessthan")
                      (">" "greaterthan")
                      ("*" "%2A")
                      ("?" "%3F")
                      ("!" "%21")
                      ))
          (utils:string-capitalize funname)))
    
    (define wiki-inner
       (lambda (funname)
          (let* ((urlbase "http://moso.com.au/wiki/index.php?title=")
                 (newname (wikiescape funname))
                 (url (string-append urlbase newname)))
             (utils:open-url url))))
    
    ;; macro wrapper and main function that gets called 
    (define-macro (wiki name)
       `(wiki-inner (sexpr->string (quote ,name))))
    
     

    >>>
    That’s it: load all of this code (or put it in a single file and load it at startup time) and you’ve got the wiki procedure available!

    ]]>
    559
    Impromptu: If-mod macro http://www.michelepasin.org/blog/2009/10/29/impromptu-if-mod-macro/ Thu, 29 Oct 2009 12:58:02 +0000 http://magicrebirth.wordpress.com/?p=401 hey there – this morning I checked out a nice screencast by Ben Swift and was struck by the if-mod construct he’s using. It’s a really useful shortcut that saves you from writing a few (possibly distracting) parenthesis, so I tried to recreate it myself.

    To recap.. normally with Impromptu if you want to play notes at some specific time expressed in beats with you’d have to set up a metronome first [have a look here for more info about how to use *metro*] and then check for the right beat using the modulo function.
    For example, something like this will play a central C every first beat of a 4/4 measure:

    
    (define *metro* (make-metro 100))
    
    (define test
       (lambda (beat)
          (if (equal? (modulo beat 4) 0)
              (play dls 60 60 3))
          (callback (*metro* (+ beat (* 1/2 1/4))) 'test (+ beat 1/4))))
    
    (test (*metro* 'get-beat 4))

    Another way of doing this is by using case. Same approach, but probably faster to code, as it lets you specify ‘multiple beats’ very easily:

    
    (define test2
       (lambda (beat)
          (case (modulo beat 4)
                ((0)
                 (play dls 60 60 3))
                ((2 5/2)
                 (play dls 67 60 1/2)))
          (callback (*metro* (+ beat (* 1/2 1/4))) 'test2 (+ beat 1/4))))
    
    (test2 (*metro* 'get-beat 4))
    

    Still quite a few parenthesis though… which, especially when playing live, might mean more chances to mess up!
    So when I saw Ben’s video I realized that a macro usable to facilitate the creation of case/modulo expressions would be quite useful..
    Here is how it can be done:

    
    (define-macro (if-mod x y args)
       `(for-each (lambda (step)
                     (if (equal? (modulo beat ,x) step)
                         ,args))
                  (if (list? ,y)
                      ,y
                      (list ,y))))
    

    Now, by using the if-mod macro we’ve just created we can re-write the second example above much more concisely:

    
    (define test2-new
       (lambda (beat)
          (if-mod 4 0 (play dls 60 60 3))
          (if-mod 4 '(2 5/2) (play dls 67 60 1/2))
          (callback (*metro* (+ beat (* 1/2 1/4))) 'test2-new (+ beat 1/4))))
    
    (test2-new (*metro* 'get-beat 4))
    

    That’s all! Notice also that the if-mod construct can take either a list of beats or a single one.

    ]]>
    401