If I had a complex if statement that I did not want to overflow simply for aesthetic purposes, what would be the most kosher way to break it up since coffeescript will interpret returns as the body of the statement in this case?
if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) or (not foo and not bar)
awesome sauce
else lame sauce
CoffeeScript will not interpret the next line as the body of the statement if the line ends with an operator, so this is ok:
# OK!
if a and
not
b
c()
it compiles to
if (a && !b) {
c();
}
so your if could be formatted as
# OK!
if (foo is
bar.data.stuff and
foo isnt bar.data.otherstuff) or
(not foo and not bar)
awesome sauce
else lame sauce
or any other line-breaking scheme so long as the lines end in and or or or is or == or not or some such operator
As to indentation, you can indent the non-first lines of your if so long as the body is even more indented:
# OK!
if (foo is
bar.data.stuff and
foo isnt bar.data.otherstuff) or
(not foo and not bar)
awesome sauce
else lame sauce
What you cannot do is this:
# BAD
if (foo #doesn't end on operator!
is bar.data.stuff and
foo isnt bar.data.otherstuff) or
(not foo and not bar)
awesome sauce
else lame sauce
This changes your code's meaning somewhat, but may be of some use:
return lame sauce unless foo and bar
if foo is bar.data.stuff isnt bar.data.otherstuff
awesome sauce
else
lame sauce
Note the is...isnt chain, which is legit, just as a < b < c is legit in CoffeeScript. Of course, the repetition of lame sauce is unfortunate, and you may not want to return right away. Another approach would be to use soaks to write
data = bar?.data
if foo and foo is data?.stuff isnt data?.otherstuff
awesome sauce
else
lame sauce
The if foo and is a little inelegant; you could discard it if there's no chance that foo is undefined.
Like any other language, by not having them in the first place. Give names to the different parts an treat them separately. Either by declaring predicates, or by just creating a couple of boolean vars.
bar.isBaz = -> #data.stuff != #data.otherstuff
bar.isAwsome = (foo) -> #isBaz() && #data.stuff == foo
if not bar? or bar.isAwesome foo
awesome sauce
else lame sauce
Escaping the linebreak looks most readable to me:
if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) \
or (not foo and not bar)
awesome sauce
else lame sauce
When a lot of low-level boilerplate occurs you should increase level of abstract.
The best solutions are:
to use good named variables and functions
logic rules in if/else statements
One of logic rules is:
(not A and not B) == not (A or B)
The first way. Variables:
isStuff = foo is bar.data.stuff
isntOtherStuff = foo isnt bar.data.otherstuff
isStuffNotOtherStuff = isStuff and isntOtherStuff
bothFalse = not (foo or bar)
if isStuffNotOtherStuff or bothFalse
awesome sauce
else lame sauce
The main disadvantage of this method is its slowness. We will get better performance if we use and and or operators features and replace variables with functions:
C = A and B
If A is false operator and wouldnt call
C = A or B
If A is true operator or wouldnt call
The second way. Functions:
isStuff = -> foo is bar.data.stuff
isntOtherStuff = -> foo isnt bar.data.otherstuff
isStuffNotOtherStuff = -> do isStuff and do isntOtherStuff
bothFalse = -> not (foo or bar)
if do isStuffNotOtherStuff or do bothFalse
awesome sauce
else lame sauce
Related
I'm new to Clojure.
In Java I can do something like this extremely contrived example:
public abstract class Foo {
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
public interface Fooable {
public void sayHello(String name);
}
public class Bar extends Foo implements Fooable, Barable {
...
}
public class Baz extends Foo implements Fooable, Barable {
...
}
So, here we have two classes, implementing the Fooable interface the same way (through their abstract base class parent) and (presumably) implementing the Barable interface two different ways.
In Clojure, I can use defrecord to define types Bar and Baz, and have them implement protocols rather than interfaces (which, essentially, are what protocols are, from what I understand). I know how to do this in the most basic sense, but anything more complex is stumping me.
Given this:
(defrecord Bar [x])
(defrecord Baz [x y])
(defprotocol Foo (say-hello [this name]))
how would I recreate the abstract base class functionality above, i.e. have one protocol implemented the same way across multiple defrecord types, without duplicating code? I could of course do this, but the code repetition makes me cringe:
(extend-type Bar
Foo
(say-hello [this name] (str "Hello, " name "!")))
(extend-type Baz
Foo
(say-hello [this name] (str "Hello, " name "!")))
There has to be a cleaner way of doing this. Again, I'm new to Clojure (and Lisp in general; I'm trying to learn Common Lisp concurrently), so macros are an entirely new paradigm for me, but I thought I'd try my hand at one. Not surprisingly, it fails, and I'm not sure why:
(defmacro extend-type-list [tlist proto fmap]
(doseq
[t tlist] (list 'extend t proto fmap)))
fmap of course is a map of functions, i.e. {:say-hello (fn [item x] (str "Hello, " x "!"))} The doseq, applied to a concrete list of record types and a concrete protocol, does work. Within the macro, of course, it doesn't, macroexpand calls return nil.
So, question 1, I guess, is "what's wrong with my macro?". Question 2 is, how else can I programmatically extend protocols for types without a lot of repetitive boilerplate code?
Your macro is returning nil because doseq returns nil.
A Clojure macro should generate a new form using a combination of syntax-quotes (`), unquotes (~), and unquote-splicing (~#) reader macros.
(defmacro extend-type-list [types protocol fmap]
`(do ~#(map (fn [t]
`(extend ~t ~protocol ~fmap))
types)))
Without using a macro, you have a few options:
(defrecord Bar [x])
(defrecord Baz [x y])
Use a simple var to hold the function map:
(defprotocol Foo (say-hello [this name]))
(def base-implementation
{:say-hello (fn [this name] (str "Hello, " name "!"))})
(extend Bar
Foo
base-implementation)
(extend Baz
Foo
base-implementation)
(say-hello (Bar. 1) "Bar") ;; => "Hello, Bar!"
(say-hello (Baz. 1 2) "Baz") ;; => "Hello, Baz!"
If you move to multimethods, you can accomplish something similar with clojure.core/derive
(defmulti say-hello (fn [this name] (class this)))
(derive Bar ::base)
(derive Baz ::base)
(defmethod say-hello ::base [_ name]
(str "Hello, " name "!"))
(say-hello (Bar. 1) "Bar") ;; => "Hello, Bar!"
(say-hello (Baz. 1 2) "Baz") ;; => "Hello, Baz!"
Question 1
Macros are just normal functions that are called at compile-time rather than run-time. If you look at the definition of defmacro, it actually just defines a function with some special meta-data.
Macros return Clojure syntax, which is spliced into the code at the point of the macro call. This means that your macro should return (quoted) syntax that looks exactly like what you would have typed manually into the source file at that point.
I find that a good way to design complex macros is to first declare it with defn, tweaking it until it returns my expected output. As with all Lisp development, the REPL is your friend! This approach requires you to manually quote any parameters being passed to your proto-macro function. If you declare it as a macro then all the arguments are treated as data (e.g. variable names are passed in as symbols), but if you call it as a function it'll try to actually evaluate the arguments if you don't quote them!
If you try this out with your macro you'll see that it doesn't actually return anything! This is because you're using doseq, which is for side-effecting computations. You want to use for in order to build up the syntax to do all of the extend-type calls. You'll probably need to wrap them in a (do ) form since a macro must return a single form.
Question 2
According to the documentation, you can actually implement multiple interfaces/protocols directly within inside the defrecord macro. After your field declaration, just add the bodies of all the extend-type forms you would have declared.
(defrecord Bar [x]
Foo1
(method1 [this y] 'do-something)
Foo2
(method2 [this y z] 'do-something-else))
It looks like the two questions you asked at the bottom have been pretty comprehensively answered, but you asked something interesting in the text of the question: "how would I recreate the abstract base class functionality above, i.e. have one protocol implemented the same way across multiple defrecord types, without duplicating code?"
If we look at the documentation for datatypes, two quotes jump out:
Concrete derivation is bad
you cannot derive datatypes from concrete classes, only interfaces
Tying polymorphism to inheritance is bad
Clojure datatypes intentionally restrict some features of Java, for example concrete derivation. So I believe the answer to your question really is, "you shouldn't". Multimethods or def'ing the functionality outside the defrecord and calling into it (like DaoWen's answer) should be preferred.
But if you really, really want to do exactly what you're doing in Java, you can use gen-class to extend a class.
(gen-class :name Bar :extends Foo :implements [Fooable])
(gen-class :name Baz :extends Foo :implements [Fooable])
Note that this implementation is a bit of a hack (you can't test in the repl because gen-class only does something when compiling), and doesn't use the :gen-class key in the ns macro like you typically would if you really had to gen-class. But using gen-class at all is a bit of a hack.
If I evaluate
(def ^:macro my-defn1 #'defn)
a macro named 'my-defn1' is defined, which I can use just like 'defn'.
However, if I evaluate instead
(if true
(def ^:macro my-defn2 #'defn))
the var for 'my-defn2' doesn't have the :macro metadata set and I can't use it as a macro, even though the 'def' form is equal to the previous case.
Here is the complete code (http://cljbin.com/paste/52322ba5e4b0fa645e7f9243):
(def ^:macro my-defn1 #'defn)
(if true
(def ^:macro my-defn2 #'defn))
(println (meta #'my-defn1)) ; => contains :macro
(println (meta #'my-defn2)) ; => doesn't contain :macro!
(my-defn1 hello1 []
(println "hello 1"))
(hello1) ; => prints "hello 1"
(my-defn2 hello2 [] ; => CompilerException: Unable to resolve
(println "hello 2")) ; symbol: hello2 in this context
What makes the behaviour different?
Clojure's def cannot really be conditionally applied. The documentation for def is IMO insufficiently strong on that part. It's not just bad style, it can cause all kinds of subtle issues.
You should only use def at the top-level, or in a do or let form at the top-level. Conditionally applying def will result in the functionality being split up in something like declare and a subsequent conditional def, but not always in the way that you'd expect/like.
You might be better off using def at the top level here and then conditionally using alter-var-root. Or use (def my-var (if .. .. ..)). Think about why you'd ever want to have a global definition "disappear".
I'm experimenting with the scala 2.10 macro features. I have trouble using LabelDef in some cases, though. To some extent I peeked in the compiler's code, read excerpts of Miguel Garcia's papers but I'm still stuck.
If my understanding is correct, a pseudo-definition would be:
LabelDef(labelName, listOfParameters, stmsAndApply) where the 3 arguments are Trees and:
- labelNameis the identifier of the label $L being defined
- listOfParameters correspond to the arguments passed when label-apply occurs, as in $L(a1,...,an), and can be empty
- stmsAndApplycorresponds to the block of statements (possibly none) and final apply-expression
label-apply meaning more-or-less a GOTO to a label
For instance, in the case of a simple loop, a LabelDef can eventually apply itself:
LabelDef($L, (), {...; $L()})
Now, if I want to define 2 LabelDef that jump to each other:
...
LabelDef($L1, (), $L2())
...
LabelDef($L2, (), $L1())
...
The 2nd LabelDef is fine, but the compiler outputs an error on the 1st, "not found: value $L2". I guess that is because $L2 isn't yet defined while there is an attempt to apply it. This is a tree being constructed so that would make sense to me. Is my understanding correct so far? Because if no error is expected, that means my macro implementation is probably buggy.
Anyway, I believe there must be a way to apply $L2 (i.e. Jumping to $L2) from $L1, somehow, but I just have no clue how to do it. Does someone have an example of doing that, or any pointer?
Other unclear points (but less of a concern right now) about using LabelDef in macros are:
-what the 2nd argument is, concretely, how is it used when non-empty? In other words, what are the mechanisms of a label-apply with parameters?
-is it valid to put in the 3rd argument's final expression anything else than a label-apply? (not that I can't try, but macros are still experimental)
-is it possible to perform a forwarding label-apply outside a LabelDef? (maybe this is a redundant question)
Any macro implementation example in the answer is, of course, very welcome!
Cheers,
Because if no error is expected, that means my macro implementation is probably buggy.
Yes, it seems that was a bug (^^; Although I'm not sure whether or not the limitation with the Block/LabelDef combination exists on purpose.
def EVIL_LABELS_MACRO = macro EVIL_LABELS_MACRO_impl
def EVIL_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // fails to expand
import c.universe._
val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2")
val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil)))
val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil)))
c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2) )
}
def FINE_LABELS_MACRO = macro FINE_LABELS_MACRO_impl
def FINE_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // The End isn't near
import c.universe._
val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2")
val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil)))
val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil)))
c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2, c.reify{println("The End")}.tree) )
}
I think a Block is parsed into { statements; expression } thus the last argument is the expression. If a LabelDef "falls in" expression, e.g. the EVIL_LABELS_MACRO pattern, its expansion won't be visible in statements; hence error "not found: value $L2".
So it's better to make sure all LabelDef "fall in" statements. FINE_LABELS_MACRO does that and expands to:
{
$L1(){
scala.this.Predef.println("$L1");
$L2()
};
scala.this.Predef.println("ignored");
$L2(){
scala.this.Predef.println("$L2");
$L1()
};
scala.this.Predef.println("The End")
}
I follow the C family (PHP is a wannabe!) requirement that a statement that spans over multiple lines must be enclosed in curlies.
Scala avoids parse errors in this code from O'Reilly's Programming Scala.
def apply(specification: String): Option[Widget] = specification match {
case ButtonExtractorRE(label) => new Some(new Button(label))
case TextFieldExtractorRE(text) => new Some(new TextField(text))
case _ => None
}
whereas I believe it should look like (the body of the function is enclosed):
def apply(specification: String): Option[Widget] = {
specification match {
case ButtonExtractorRE(label) => new Some(new Button(label))
case TextFieldExtractorRE(text) => new Some(new TextField(text))
case _ => None
}
}
while Scala can parse it, can a programmer "get it"? I dont. Am I missing some intuitive idea?
Should I rather avoid such a practice, if it leads to practical problems (like poor readability?
In Scala much more things (including if, match and for with yield) return a result as in other languages. And more data structures are immutable, which often leads to transformation chains of map, filter, flatMap, collect etc - which also gives just one result. Last but not least Scala has excellent support for tuples, which means that you often get back a tuple as a single result where other languages have to sort out single values.
So in general Scala doesn't deal as much with variables storing intermediate values as other languages do. That means a function is often just an equation f(a) = b, where b might be quite complex, but is still one chain returning a single result. So it is just naturally to adopt that syntax, which makes immediately clear that you are not juggling with intermediate results, but that you follow a more functional style.
It should be mentioned that functional languages (except the "lispy" family with a quite different syntax) have similar conventions. So if you look at Haskell, F# or Erlang, you usually won't see any "blocks" for methods. There are structures like let, case and (for Haskell) do which might look a little bit like blocks, but are expressions as well.
When you say a function = (without the curly braces), it compiles and works fine because it's a single expression. Your 'match' expression always evaluates to one single value. And the 'match' is the only thing in your function. So, really it's only a single expression, even if it spans a few lines. If your apply function requires multiple expressions and statements, then yes, you do need curly braces.
I follow the C family requirement that a statement that spans over multiple lines must be enclosed in curlies.
Wrong.
#include <iostream>
using namespace std;
int main() {
bool b = true;
char c = 'a';
if (b) switch (c) {
case 'a': cout << "It's a" << endl; break;
default : cout << "Not a" << endl; break;
}
}
Here the true branch of the if statement spans multiple lines, but is not enclosed in braces. In fact, have you ever used if/else if?
if (foo) {
// do foo stuff
else if (bar) {
// do bar stuff
} else {
// do non-foo/bar stuff
}
Syntactically, there is no special treatment for else if. else is just a regular key word. This is syntactically equivalent to
if (foo) {
// do foo stuff
else {
if (bar) {
// do bar stuff
} else {
// do non-foo/bar stuff
}
}
Note that brackets are not required to surround the inner if. This is because an if/else statement is a self-contained single expression. The rule is not to put braces around any statement that spans multiple lines. Rather, I think it fair to say that any statements separated by semicolons must be grouped with braces. Disclaimer: I am not a C expert. Check the docs if you need to be sure.
Nor am I a Scala expert, but generally I think the Scala mindset is to remove braces whenever possible, subject to good judgement and taste, of course.
You have a function that consists only of a single expression. Many languages still require to enclose it in curly braces.
This might be confusing if you are only used to such languages. But after using Scala a little a function definition with a single expression as body starts to look like a function valued 'variable'.
From that point you'll stop missing the curly braces.
So: in almost all cases I'd skip all the braces I don't need. I had not a problem with it in a long time.
I'm pretty new to Scala, but I thought that one of the strengths of the language was to remove the ceremony, like parenthesis and dots, that exists in for instance Java. So I was pretty confused when I discovered that I can write for instance
str1 equals str2
but not
println "Hello world"
I have surmised that it has something to do with that the first example has three "parts", but the second has only two, but I'm struggling to understand why it is so.
When there are only two parts, the expression is seen as method invocation. I.e. the only possibility for
println "Hello, world"
would be
println."Hello, world"
which of course does not make much sense here. (***** see below for an addition)
If you like, however, you can write Console println "Hello, World" to resolve the ambiguity.
It doesn’t look that ambigus in the string example, a string could hardly be a method name, but think of the following:
class B
val b = new B
object A {
def apply(myB: B) { print("apply") }
def b { print("b") }
}
Now, when writing A b, what do I get. How should it be interpreted? It turns out that:
A b // "b"
A.b // "b"
A(b) // apply
So, there is a clear rule what to do in a two part expression. (I hope nobody starts splitting hairs about apply and real method invocation…)
Addition
With the advent of dynamic classes, you can toy around a little and define the following
object println extends Dynamic {
def typed[T] = asInstanceOf[T]
def applyDynamic(name: String)(args: Any*) = Console.println(name)
}
And now look!, no parentheses:
println `Hello, world` // prints, "Hello, world"
Of course, please don’t do that in front of children or in real-life code.
You could rewrite your second example with three "parts", in which case it would compile without parentheses:
Predef println "Hello world"
(Just for illustration purposes -- #Debilski's answer is perfect!)