Hiding Internal State of CoffeeScript Object - coffeescript

Looking at the following from CoffeeScript Ristretto:
QueueMaker = ->
do (queue = undefined) ->
array: []
head: 0
tail: -1
pushTail: (value) ->
queue.array[tail += 1] = value
pullHead: ->
unless queue.isEmpty()
do (value = queue.array[queue.head]) ->
queue.array[queue.head] = undefined
queue.head += 1
value
isEmpty: ->
queue.tail < queue.head
It's possible to mutate queue.head - http://jsfiddle.net/VQLNG/.
queue = QueueMaker()
queue.head = 666
console.log queue
How can I write the above function so that head isn't public?

JavaScript doesn't have private properties so CoffeeScript doesn't have them either.
However, you can simulate private properties in many cases by using function scopes to hide things and closures to access the hidden things.
A simple stack implementation should demonstrate the technique:
Stack = ->
stack = [ ]
push: (e) -> stack.push(e)
pop: -> stack.pop()
toArray: -> stack.slice()
stack is a local variable in the Stack function so it cannot be accessed or seen from outside Stack. The push and pop functions simply proxy to the stack array and the toArray function is the only way to see what stack looks like. Only those three functions have access to stack so it is effectively private and each time you call Stack, you get a new local stack.
Demo: http://jsfiddle.net/ambiguous/C8V5R/
Adapting your queue to use this technique to hide array, head and tail is left as an exercise.

The return value of QueueMaker is a JavaScript object, with head being one of it's fields. Object fields are mutable, with no option for protected status.
Even with QueueMaker rewritten as a CoffeeScript class, and head being an instance variable, it would still be mutable from outside the object scope.
CoffeeScript can only support the language level features of JavaScript, which does not support private/protected keywords. Sadly.

QueueMaker = ->
do (array = [], head = 0, tail = -1) ->
pushTail: (value) ->
array[tail += 1] = value
pullHead: ->
if tail >= head
do (value = array[head]) ->
array[head] = undefined
head += 1
value
isEmpty: ->
tail < head
With this version, array, head and tail are hidden. They are initialed when the queue is created, and remain in existence only as long as it exists.
coffee> queue = QueueMaker()
{ pushTail: [Function],
pullHead: [Function],
isEmpty: [Function] }
coffee> queue.head
undefined
But to be honest, this is the first version of QueueMaker on the Ristretto link. What you gave us was the “de-encapsulate” version, rewritten purposely to make these variables visible (in order to extend its behavior).
For reference, the "de-encapuslated" version is:
QueueMaker = ->
do (queue = undefined) ->
queue =
array: []
head: 0
tail: -1
pushTail: ...
pullHead: ...
Your question omitted the queue= line. Now the purpose of the do()-> should be clearer.

Related

Return keyword inside the inline function in Scala

I've heard about to not use Return keyword in Scala, because it might change the flow of the program like;
// this will return only 2 because of return keyword
List(1, 2, 3).map(value => return value * 2)
Here is my case; I've recursive case class, and using DFS to do some calculation on it. So, maximum depth could be 5. Here is the model;
case class Line(
lines: Option[Seq[Line]],
balls: Option[Seq[Ball]],
op: Option[String]
)
I'm using DFS approach to search this recursive model. But at some point, if a special value exist in the data, I want to stop iterating over the data left and return the result directly instead. Here is an example;
Line(
lines = Some(Seq(
Line(None, Some(Seq(Ball(1), Ball(3))), Some("s")),
Line(None, Some(Seq(Ball(5), Ball(2))), Some("d")),
Line(None, Some(Seq(Ball(9))), None)
)),
balls = None,
None
)
In this data, I want to return as like "NOT_OKAY" if I run into the Ball(5), which means I do not need to any operation on Ball(2) and Ball(9) anymore. Otherwise, I will apply a calculation to the each Ball(x) with the given operator.
I'm using this sort of DFS method;
def calculate(line: Line) = {
// string here is the actual result that I want, Boolean just keeps if there is a data that I don't want
def dfs(line: Line): (String, Boolean) = {
line.balls.map{_.map { ball =>
val result = someCalculationOnBall(ball)
// return keyword here because i don't want to iterate values left in the balls
if (result == "NOTREQUIRED") return ("NOT_OKAY", true)
("OKAY", false)
}}.getOrElse(
line.lines.map{_.map{ subLine =>
val groupResult = dfs(subLine)
// here is I'm using return because I want to return the result directly instead of iterating the values left in the lines
if (groupResult._2) return ("NOT_OKAY", true)
("OKAY", false)
}}
)
}
.... rest of the thing
}
In this case, I'm using return keyword in the inline functions, and change the behaviour of the inner map functions completely. I've just read somethings about not using return keyword in Scala, but couldn't make sure this will create a problem or not. Because in my case, I don't want to do any calculation if I run into a value that I don't want to see. Also I couldn't find the functional way to get rid of return keyword.
Is there any side effect like stack exception etc. to use return keyword here? I'm always open to the alternative ways. Thank you so much!

How to do a case insensitive match for command line arguments in scala?

I'm working on a command line tool written in Scala which is executed as:
sbt "run --customerAccount 1234567"
Now, I wish to make this flexible to accept "--CUSTOMERACCOUNT" or --cUsToMerAccount or --customerACCOUNT ...you get the drift
Here's what the code looks like:
lazy val OptionsParser: OptionParser[Args] = new scopt.OptionParser[Args]("scopt") {
head(
"XML Generator",
"Creates XML for testing"
)
help("help").text(s"Prints this usage message. $envUsage")
opt[String]('c', "customerAccount")
.text("Required: Please provide customer account number as -c 12334 or --customerAccount 12334")
.required()
.action { (cust, args) =>
assert(cust.nonEmpty, "cust is REQUIRED!!")
args.copy(cust = cust)
}
}
I assume the opt[String]('c', "customerAccount") does the pattern matching from the command line and will match with "customerAccount" - how do I get this to match with "--CUSTOMERACCOUNT" or --cUsToMerAccount or --customerACCOUNT? What exactly does the args.copy (cust = cust) do?
I apologize if the questions seem too basic. I'm incredibly new to Scala, have worked in Java and Python earlier so sometimes I find the syntax a little hard to understand as well.
You'd normally be parsing the args with code like:
OptionsParser.parse(args, Args())
So if you want case-insensitivity, probably the easiest way is to canonicalize the case of args with something like
val canonicalized = args.map(_.toLowerCase)
OptionsParser.parse(canonicalized, Args())
Or, if you for instance wanted to only canonicalize args starting with -- and before a bare --:
val canonicalized =
args.foldLeft(false -> List.empty[String]) { (state, arg) =>
val (afterDashes, result) = state
if (afterDashes) true -> (arg :: result) // pass through unchanged
else {
if (arg == "==") true -> (arg :: result) // move to afterDash state & pass through
else {
if (arg.startsWith("--")) false -> (arg.toLowerCase :: result)
else false -> (arg :: result) // pass through unchanged
}
}
}
._2 // Extract the result
.reverse // Reverse it back into the original order (if building up a sequence, your first choice should be to build a list in reversed order and reverse at the end)
OptionsParser.parse(canonicalized, Args())
Re the second question, since Args is (almost certainly) a case class, it has a copy method which constructs a new object with (most likely, depending on usage) different values for its fields. So
args.copy(cust = cust)
creates a new Args object, where:
the value of the cust field in that object is the value of the cust variable in that block (this is basically a somewhat clever hack that works with named method arguments)
every other field's value is taken from args

Can't get query results outside the function

I have this class in which i try to initialize array attributes with query results:
class data
minute: []
hour: []
constructor: () ->
findMin = events.find({"aggr":"minute"}).sort({$natural:-1}).limit(120)
findHour = events.find({"aggr":"hour"}).sort({$natural:-1}).limit(14)
findMin.execFind (errMin, resMin) ->
for recMin in resMin
#minute.push recMin
findHour.execFind (errH, resH) ->
for recH in resH
#hour.push recH
So i call smth = new data() and console.log smth and get an empty attributes and an error about undefined not having 'push' method. While i can understand an error i cant get why my arrays are empty. Dont get me wrong - i know this error causes them to be empty, but i tried several kinds of variants. And ive read about acync and callbacks, but still don't have a clue how to use callbacks not to 'alert' smth, but to use it afterwards. If you could help me with that or with some links that could - i would appreciate it SO much.
You have two issues. The one that is causing the error you are observing is that '#' inside of your two callbacks is not bound to your data instance, so you need to use =>. Secondly, and as pointed out by #AaronDufour, your hour and minute arrays are declared at the class level so they will be shared between every instance of data, which I doubt is what you want, so you need to move them into your constructor.
class data
constructor: () ->
#minute = []
#hour = []
findMin = events.find({"aggr":"minute"}).sort({$natural:-1}).limit(120)
findHour = events.find({"aggr":"hour"}).sort({$natural:-1}).limit(14)
findMin.execFind (errMin, resMin) =>
for recMin in resMin
#minute.push recMin
findHour.execFind (errH, resH) =>
for recH in resH
#hour.push recH
I assume you want minute and hour to be instance variables? They must be initialized in the constructor. The way you're doing it now, they're on the prototype, so it won't work properly. Try this:
class data
constructor: () ->
#minute = []
#hour = []
findMin = events.find({"aggr":"minute"}).sort({$natural:-1}).limit(120)
findHour = events.find({"aggr":"hour"}).sort({$natural:-1}).limit(14)
findMin.execFind (errMin, resMin) =>
for recMin in resMin
#minute.push recMin
findHour.execFind (errH, resH) =>
for recH in resH
#hour.push recH

Coffeescript isn't empty object [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
is object empty?
update: (id, data) ->
toUpdate = #find(id)
if toUpdate isnt {}
console.log "hi mom"
console.log toUpdate
toUpdate.setProperty(key, value) for own key, value of data
return toUpdate
find:(id) ->
result = record for record in #storage when record.id is id
return result or {}
Given the following Mocha tests
describe '#update', ->
it 'should return an updated record from a given id and data when the record exists', ->
boogie = createData()
archive = new Archive("Dog")
dog = archive.create(boogie)
result = archive.update(1, {name:"Chompie", age:1})
result.name.should.eql "Chompie"
result.age.should.eql 1
result.emotion.should.eql dog.emotion
it 'should return an updated record from a given id and data when the record does not exist', ->
boogie = createData()
archive = new Archive("Dog")
dog = archive.create(boogie)
result = archive.update(50, {name:"Chompie", age:1})
result.should.not.exist
The result is
Archive #update should return an updated record from a given id and data when the record exists: hi mom
{ id: 1,
validationStrategies: {},
name: 'Boogie',
age: 2,
emotion: 'happy' }
✓ Archive #update should return an updated record from a given id and data when the record exists: 1ms
Archive #update should return empty when the record does not exist: hi mom
{}
✖ 1 of 13 tests failed:
1) Archive #update should return empty when the record does not exist:
TypeError: Object #<Object> has no method 'setProperty'
...surprising, isnt it?
CoffeeScript's is (AKA ==) is just JavaScript's === and isnt (AKA !=) is just JavaScript's !==. So your condition:
if toUpdate isnt {}
will always be true since toUpdate and the object literal {} will never be the same object.
However, if #find could return a known "empty" object that was available in a constant, then you could use isnt:
EMPTY = {}
find: ->
# ...
EMPTY
and later:
if toUpdate isnt EMPTY
#...
For example, consider this simple code:
a = { }
b = { }
console.log("a is b: #{a is b}")
console.log("a isnt b: #{a isnt b}")
That will give you this in your console:
a is b: false
a isnt b: true
But this:
class C
EMPTY = { }
find: -> EMPTY
check: -> console.log("#find() == EMPTY: #{#find() == EMPTY}")
(new C).check()
will say:
#find() == EMPTY: true
Demo: http://jsfiddle.net/ambiguous/7JGdq/
So you need another way to check if toUpdate isn't empty. You could count the properties in toUpdate:
if (k for own k of toUpdate).length isnt 0
or you could use the special EMTPY constant approach outlined above. There are various other ways to check for an empty object, Ricardo Tomasi​ has suggested a few:
Underscore offers _.isEmpty which is basically the for loop approach with some special case handling and a short circuit.
Underscore also offers _.values so you could look at _(toUpdate).values().length. This calls map internally and that will be the native map function if available.
You could even go through JSON using JSON.stringify(toUpdate) is '{}', this seems a bit fragile to me and rather round about.
You could use Object.keys instead of the for loop: Object.keys(toUpdate).length isnt 0. keys isn't supported everywhere though but it will work with Node, up-to-date non-IE browsers, and IE9+.
Sugar also has Object.isEmpty and jQuery has $.isEmptyObject.
A short-circuiting for loop appears to be the quickest way to check emptiness:
(obj) ->
for k of toUpdate
return true
false
That assumes that you don't need own to avoid iterating over the wrong things. But given that this is just a test suite and that an emptiness test almost certainly won't be a bottle neck in your code, I'd go with whichever of Underscore, Sugar, or jQuery you have (if you need portability and have to deal with the usual browser nonsense), Object.keys(x).length if you know it will be available, and (k for own k of toUpdate).length if you don't have the libraries and have to deal with browser nonsense and aren't certain that toUpdate will be a simple object.

How to implement array.any() and array.all() methods in Coffeescript?

How to implement array.any() and array.all() methods in Coffeescript?
Those are actually part of Javascript 1.6 and will work just the same in CoffeeScript. You want some and every.
I don't know what environment you're in, but IE < 9 doesn't seem to support those methods. They're pretty easy to add. There's a snippet of code on those pages that show you compatibility code and if you want you can translate them to CoffeeScript, though you don't have to.
A cruder, simpler way would be (untested):
if not Array.prototype.some
Array.prototype.some = (f) -> (x for x in # when f(x)).length > 0
if not Array.prototype.every
Array.prototype.every = (f) -> (x for x in # when f(x)).length == #length
But neither of those have short circuit logic. Edit: But see Ricardo's answer for a better version of them.
Short-circuited (optimized) versions:
Array.prototype.some ?= (f) ->
(return true if f x) for x in #
return false
Array.prototype.every ?= (f) ->
(return false if not f x) for x in #
return true
The ?= is for "existential assignment", only runs when that property is null/undefined.
Check out underscore.js, which provides you with _.any and _.all methods (a.k.a. _.some and _.every) that will run in any major JS environment. Here's how they're implemented in CoffeeScript in underscore.coffee:
_.some = (obj, iterator, context) ->
iterator ||= _.identity
return obj.some iterator, context if nativeSome and obj.some is nativeSome
result = false
_.each obj, (value, index, list) ->
_.breakLoop() if (result = iterator.call(context, value, index, list))
result
_.every = (obj, iterator, context) ->
iterator ||= _.identity
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
result = true
_.each obj, (value, index, list) ->
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
result
(These depend on _.each, which is a straightforward iteration method, and _.breakLoop, which just throws an exception.)
I was looking at this today and decided to implement all as a fold, and I suppose you could do the same for any as well (but it doesn't short circuit, either):
all = (someArray, predicate) ->
reduceAll = (left, right) ->
return left and right
return [predicate(elem) for elem in someArray].reduce(reduceAll, true)
The non-short-circuiting any would be mostly similar:
reduceAny = (left, right) ->
return left or right
[p(elem) for elem in someArray].reduce(reduceAny, false)
I did all this way because I found it to be readable. Also, I just did it as a free-floating function instead of an array method.