The syntax of a language is the primary interface to that language. SyntacticAbstraction allows the programmer to make the syntax easier to use, in the same way that data abstraction makes data easier to use.
Languages supporting programmer extensible syntax:
Ok, here's a question for the SmalltalkerLanguage? programmers. In OnLisp one of the common idioms is to have a function return false on non-fatal error and some other value otherwise. So a common idiom to deal with this sort of function is
(let ((result (function-that-can-return-#f))) (if result (do-something-useful result) (carry-on)))In C-ish pseudo code:
result = function_that_can_return_#f if (result) { do_something_useful(result); } else { carry_on(); }One of Paul Grahams macros in OnLisp is called aif. It simplifies this idiom by getting rid of the let. You can write
(aif (function...) (do-something-useful it) (carry-on))However, its real power is because it creates a new variable in the current scope, so you can refer to other variables in the current scope:
(let ((variable a-value)) (aif (function...) (do-something-useful it variable) (carry-on)))This is useful in many languages. For example, in Java when one reads from a file you have to check for null. Say you are processing each line with a regexp:
Regexp csv = new Regexp("((.*),)*"); String line = bufferedReader.readLine(); if (line != null) { getValues(regexp, line) } else { carryOn(); }You can write this easily with aif:
Regexp csv = new Regexp("((.*),)*"); aif (bufferedReader.readLine()) { getValues(regexp, it) } else { carryOn(); }This is something you can't do with blocks. It's not emulating LazyEvaluation but introducing a new binding in the existing scope. However, I have a feeling that this idiom isn't appropriate for SmalltalkLanguage as lexical scoping isn't such a widely used feature of the language. Thoughts? Is this an example of a SyntacticAbstraction that isn't applicable across all languages?
I'm not sure I understand the usage or that I've encountered the desire to do it in Smalltalk. In general I've come to feel that language extension as commonly done in Lisp is less appropriate in most other languages. But for this one, why not something like
function: arg onSuccess: aBlock (function: arg) ifTrue: [aBlock value]used as in
someone function: foo onSuccess: [self doSomethingUseful]This isn't the same. I've expanded the example above to show how adding the binding to the current scope is useful
How about this? (I don't know any Smalltalk worth mentioning, so the details may be wrong.)
try: funcBlock whenResultSatisfies: aPredicateBlock do: aBlock |result| result := funcBlock value. (aPredicateBlock result) ifTrue: [aBlock result] bufferedReader try: [self readline] whenResultSatisfies: [:it | it isOK] do: [:it | getValues from: it matching: regexp]-- GarethMcCaughan (a fan of Lisp macros but not terribly excited by anaphora)
I'm trying to get a discussion on the uses of syntactic abstraction and where it is appropriate rather than how to do it in any particular language. So what excites you about Lisp macros? --NoelWelsh
Two things, mostly
(defmacro foo (arg1 arg2) `(progn ,@(some-complex-calculation arg1) ,@(another-complex-calculation arg2)))or
(defmacro foo (list) `(progn (foo-something (mapcar #'blah ,list))))Does that help, or am I still being too abstract? --AlainPicard
So you do this to avoid runtime computation, in the same way some C++ templates try to do computation at compile time via template expansion?
Does the ability in PerlLanguage to have source-code filtering through another perl program, used to approximate in perl5 some of the syntax of perl6, or to implement (effectively) a compiler for a new language to perl, count as an instance of SyntacticAbstraction? -- MartinRudat
I dunno, but PerliGata seems pretty darned impressive. -- JonathanTang