oakes / play-clj

A Clojure game library
The Unlicense
940 stars 72 forks source link

Fixes for issues #103, #104 and #105 #106

Closed ghost closed 7 years ago

ghost commented 7 years ago

Benefits of using defmacro instead of defn: ensures that the return value of key-code and button-code are numbers.

Drawbacks of using defmacro instead of defn: the key-code and button-code macros accept (and parse!) symbols. For instance:

(= (key-code a) (key-code :a))
true

such that wrapping the macro in a function is impossible: (map (fn [a] (key-code a)) [:a :b :c :d])


Compare the implementations of defn with defmacro:

(key-code :w)
51

Using defn instead of defmacro allows for composability, but the return value is not a number:

(key-code :w)
com.badlogic.gdx.Input$Keys/W

I submit that this is the more desirable behavior. For one thing, we can tell at a glance what the value is-- we know that it is associated with the W key-- 51 is just an arbitrary encoding. Equality semantics are still satisfied.

This would be erronous with the defmacro implementation of key-code, but valid for the defn implementation:

(clojure.set/superset?
        #{(key-code :a) (key-code :b) (key-code :c)}
        (into #{} (map (fn [a] (key-code a))) #{:a :b}))
oakes commented 7 years ago

The key-code macro is just meant to be a convenient way to get the static fields in com.badlogic.gdx.Input$Keys. This is important since those numerical values are what you get from the :on-key-down event. See, for example, right here.

This change would break that code and others like it. I'm not clear on what the purpose would be of getting an unevaluated symbol from key-code. What would you do with it?

ghost commented 7 years ago

It is critical that key-code does not parse symbols, otherwise it is impossible to wrap it in a function for use with maps, filters, reductions or other clojure functions.

Changing defmacro to defn is the simplest way to ensure that a symbol as an argument gets evaluated instead of parsed, but its not the only way.

It is nice but it isn't vital that the return value be an unevaluated symbol. It could be a number.

Given your reply, I suggest a more involved fix that uses defn instead of defmacro and which returns a number rather than an unevaluated symbol.

oakes commented 7 years ago

Perhaps it would work if you ran the result through eval. That would evaluate the symbol into a number. I'll try it out.

oakes commented 7 years ago

I added eval so it continues to behave the same way. I also made key-pressed? and button-pressed? into functions as well. Thanks for your help!