I come from a C#/Java background which use a class based OO system and I don't get the JavaScript/CoffeeScript prototype OO system yet. I've written a CoffeeScript class below which allows me to display names for contacts according to a system-side preference. I can only get the class to work by making the joinNonEmpty(stringList, joinText) method belong to the prototype and calling it the way I would call a static method in Java/C# land.
Is there a way I can make this method call using this.joinNonEmpty(...)?
Can you shed some light on why I can reference the firstLastRender, lastFirstRender and firstOrNickThenLast methods in the constructor with this. but it doesn't work from those methods when calling the joinNonEmpty helper?
Does this have something to do with how I'm locating the appropriate method via the preference map?
prefs = displayNameFormat: "FirstOrNickThenLast"
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
# Why does this method have to be static (a class method)?
#joinNonEmpty: (stringList, joinText) ->
nonEmptyStrings = []
for s in stringList
nonEmptyStrings.push(s) if s isnt null and s isnt ""
nonEmptyStrings.join(joinText)
firstLastRender: (contact) ->
# TypeError: Object expected.
joinNonEmpty([contact.firstName, contact.lastName], ' ')
lastFirstRender: (contact) ->
# TypeError: Object doesn't support this method or property
this.joinNonEmpty([contact.lastName, contact.firstName], ', ')
firstOrNickThenLast: (contact) ->
# Works correctly.
DisplayNameRenderer.joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#prefToRenderMap[prefs.displayNameFormat](contact)
contact = firstName: "Jonathan", nickname: "Jonny", lastName: "Appleseed"
dnr = new DisplayNameRenderer()
# => "Jonny Appleseed"
console.log dnr.render(contact)
Thanks for taking the time to answer.
this (AKA #) is determined when the function is called (with exceptions as below). So when you do this:
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
You're storing unbound references to the three functions in the #prefToRenderMap instance variable and #prefToRenderMap is itself an object. Then you try to call the methods in your DisplayNameRenderer instance like this:
#prefToRenderMap[prefs.displayNameFormat](contact)
and everything falls apart because the methods are called in the wrong context and # isn't what they're expecting it to be. If prefs is 'FirstOrNickThenLast' then you're effectively doing this:
#prefToRenderMap.FirstOrNickThenLast(contact)
and # (AKA this) will be #prefToRenderMap inside the firstOrNickThenLast method. But, of course, #prefToRenderMap doesn't have any of the methods that you're trying to call so you get various errors.
One solution is to use the fat arrow (=>) to define the methods:
The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot.
So you could have things like this:
joinNonEmpty: (stringList, joinText) ->
#...
firstLastRender: (contact) =>
#joinNonEmpty([contact.firstName, contact.lastName], ' ')
and everything will work out. Here's a stripped down demo that will also show you your this problem:
http://jsfiddle.net/ambiguous/RAPJw/1/
You could also avoid this problem by referring to the methods by their names. Given a method name in a string, m = 'some_method', you can call that method like this o[m]() in both JavaScript and CoffeeScript and the result will be the same as if you said o.some_method(). A better structure would look more like this:
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstOrNickThenLast: 'firstOrNickThenLast'
joinNonEmpty: (stringList, joinText) ->
#...
firstOrNickThenLast: (contact) ->
#joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#[#prefToRenderMap['FirstOrNickThenLast']](contact)
Note the change to the structure of #prefToRenderMap and how it is used in render. And a demo of this approach: http://jsfiddle.net/ambiguous/DFYwu/
As an aside, instead of saying ClassName.class_method() inside an instance method, you can use the constructor property instead: #constructor.class_method(). Also, you usually say #method() or #property rather than this.method() and this.property in CoffeeScript.
Related
Using MobX 3 in Coffeescript, I could do this:
mobx = require 'mobx'
state = mobx.observable
items:['a','b']
compute = (key,fn)->
obj = {}
obj[key] = mobx.computed fn.bind state
mobx.extendObservable state, obj
compute 'num', ->
#items.length
mobx.autorun ->
console.log "items = #{state.items}"
mobx.autorun ->
console.log "num = #{state.num}"
state.items.push 'c'
...which works as expected,
but with MobX 4 that same codes gives the error:
Error: [mobx] Passing a 'computed' as initial property value is no
longer supported by extendObservable. Use a getter or decorator
instead
All of the examples that I can find use Javascript with Classes and Decorators and Getters.
But Coffeescript does not really do "decorators" or "getters", and I would prefer not to use Classes ( I am old-school )
So...how can I create a computed "num" on my "state"?
Can my "compute()" function be altered to make it all work again?
Ok, I figured-out how to do it, and since there have been no answers....here it is:
compute = (key,fn)->
Object.defineProperty observable_state, key,
get: fn
configurable: true
obj = {}
obj[key] = mobx.computed
mobx.decorate observable_state,obj
First, you create a configurable "getter" (it must be configurable because MobX is going to re-configure it), then you call the "decorate" function ( instead of using ES6 decorators ).
I'm fairly new to lua and have the following problem with an assignment from a class:
We currently extend lua to support objects and inheritance. The Syntax for that is
Class{'MyClass',
attribute1 = String,
attribute2 = Number
}
Class{'MySubClass', MyClass,
attribute3 = Number
}
This works perfectly fine. The real problem lies within the next task: We should support "recursive types", that means a call like
Class{'MyClass', attribute = MyClass}
should result in an class with a field of the same type as the class. When this "class-constructor" is called the variable MyClass is nil, thats why the parameter table doesnt't have an entry attribute. How is it possible to access this attribute?
My first thought was using some kind of nil-table which gets returned every time the global __index is called with an unset key. This nil-table should behave like the normal nil, but can be checked for in the "class-constructor". The problem with this approach are comparisons like nil == unknown. This should return true, but as the __eq meta method of the nil-table is never called we cannot return true.
Is there another approach I'm currently just ignoring? Any hint is greatly appreciated.
Thanks in advance.
Edit:
Here the relevant part of the "testfile". The test by which the code is rated in class is another one and gets published later.
three = 3
print( three == 3 , "Should be true")
print( unknown == nil , "Should be true" )
Class{'AClass', name = String, ref = AClass}
function AClass:write()
print("AClass:write(), name of AClass:", self.name)
end
aclass = AClass:create("A. Class")
aclass:write()
Since MyClass is just a lookup in the global table (_G), you could mess with its metatable's __index to return a newly-defined MyClass object (which you would later need to fill with the details).
However, while feasible, such an implementation is
wildly unsafe, as you could end up with an undefined class (or worse, you may end up inadvertantly creating an infinite lookup loop. Trust me, I've been there)
very hard to debug, as every _G lookup for a non-existing variable will now return a newly created class object instead of nil (this problem could somewhat be reduced by requiring that class names start with an uppercase character)
If you go that route, be sure to also override __newindex.
How about providing the argument in string form?
Class{'MyClass', attribute = 'MyClass'}
Detect strings inside the implementation of Class and process them with _G[string] after creating the class
Or alternatively, use a function to delay the lookup:
Class{'MyClass', attribute = function() return MyClass end}
I have a "class" in coffee script whose instance variables I want to initialize with instance methods that return a value via a callback, but it doesn't work as I had hoped:
EventEmitter = require('events').EventEmitter
class MyClass extends EventEmitter
constructor: ->
#datamember: setDatamember()
setDatamember: ->
someFunction (response) ->
#datamember = response
#emit 'init'
getDatamember: ->
return #datamember
----
myObj = new MyClass
myObj.on 'init', ->
console.log myObj.getDatamember
The result I get suggests that "this" in setDatamember is referring to something different from what "this" refers to in the object instance. If I explicitly call myObj.setDatamember, I get the expected result, but is there any way to call on a set method -- specifically one that sets the data member via a callback -- in the constructor? I've looked through the docs, as well as various other sources of coffeescript info (e.g. this one), and I haven't found anything that touches upon this.
Try using a fat arrow for the anonymous function:
setDatamember: ->
someFunction (response) =>
#datamember = response
#emit 'init'
Also, you'll need to call the correct function in the constructor:
constructor: ->
#setDatamember()
In general, avoid fat arrows on methods - the way Coffee-Script implements this does some bad things to memory usage. Also, it will rarely be necessary.
However, anonymous functions that refer to this will almost always need fat arrows. this is not held in closure like normal variables, and will only be set by binding (Function.prototype.bind) or by calling it as an object method (obj.myMethod() will set this to obj in myMethod).
Try using fat arrows on everything except the constructor:
class MyClass
constructor: ->
#setDatamember()
setDatamember: =>
someFunction (response) =>
#datamember = response
getDatamember: =>
return #datamember
However, you also look to have someFunction in there as an asynchronous function, so you'll never be able to just do
mc = new MyClass
console.log mc.datamember
Because that doesn't wait for someFunction to return before accessing mc.datamember.
class #A
A_Function_Alias: => #my_function
my_function: =>
usage_of_alias: =>
#A_Function_Alias.call()
What i want, is usage_of_alias to be
usage_of_alias: =>
#A_Function_Alias
And have it behave the same. i.e. I want a more functional style syntax here. I've tried multiple combinations with no success. The fact that i have to evaluate my function to get the goodies inside bothers me.
One application would be instead of this:
event: => new Event(#my_function)
which is accessed as event.call().hi()
i could have some other declaration that would allow me to access event as event.hi()
Something that behaves more like a field instead of a property.
I'm thinking you want this:
class #A
my_function: => alert 'my function!'
A_Function_Alias: #::my_function
usage_of_alias: =>
#A_Function_Alias()
# some other code...
See what this compiles to here.
When evaluating a class # is the class constructor object, the class object itself. And the :: operator lets you drill into the prototype. So #::foo in a class body compiles to MyClass.prototype.foo.
So what this is doing is first making a normal instance method named my_function, defined on A.prototype.my_function. Then we make a new instance method named A_Function_Alias and directly assign the function from class objects prototype that we just created. Now my_function and A_Function_Alias both point to the exact same function object.
But as a more sane alternative, might I suggest a pattern that defines a private inner function that the class can use, and then assigning it more directly, without crazy the prototype accessing?
class #A
# Only code inside this class has access to this local function
innerFunc = -> alert 'my function!'
# Assign the inner funciton to any instance methods we want.
my_function: innerFunc
A_Function_Alias: innerFunc
usage_of_alias: =>
#A_Function_Alias()
# or
#my_function()
# or
innerFunc()
# they all do the same thing
I'm using MooseX::Declare and methods, which uses MooseX::Method::Signatures. Let's say I have a class 'foo' with a method 'bar', and I've implemented it like:
class foo {
method bar (Str $str, Bool :$flag = 1) {
# ....
}
}
I now want to write a front-end interface that asks a user what class they want to use, what method on that class they want to use, and then what options to the method they want. I can do the first two things, so let's say the user has now chosen class foo and method bar.
But how do I find out that method bar takes a string as the first argument, and a flag => bool key value pair that defaults to 1? My code needs to know this so I can then ask the user to supply these things.
First, get the method meta object:
my $method = $class->meta->find_method_by_name( $method_name );
Then, make sure it's a signaturey method:
confess "not method with a signature!"
unless $method->isa('MooseX::Method::Signatures::Meta::Method');
Get its signature:
my $sig = $method->parsed_signature;
Then look at $sig's named_params and positional_params as detailed in the Parse::Method::Signatures::Sig docs.
To find parsed_signature, I had to look at the source to MooseX::Method::Signatures::Meta::Method… so be wary when you do this.