Coffeescript isn't empty object [duplicate] - coffeescript

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.

Related

Call a PostgreSQL function and get result back with no loop

I have a simple rust program that interacts with a PostgreSQL database.
The actual code is:
for row in &db_client.query("select magic_value from priv.magic_value();", &[]).unwrap()
{
magic_value = row.get("magic_value");
println!("Magic value is = {}", magic_value);
}
And.. it works. But I don't like it: I know this function will return one and only one value.
From the example I found, for example here: https://docs.rs/postgres/latest/postgres/index.html
and here: https://tms-dev-blog.com/postgresql-database-with-rust-how-to/
You always have a recordset to loop on.
Which is the clean way to call a function without looping?
query returns a Result<Vec<Row>, _>. You are already unwrapping the Vec, so you can just use it directly instead of looping. By turning the Vec into an owning iterator yourself, you can even easily obtain a Row instead of a &Row.
magic_value = db_client.query("select magic_value from priv.magic_value();", &[])
.unwrap() // -> Vec<Row>
.into_iter() // -> impl Iterator<Item=Row>
.next() // -> Option<Row>
.unwrap() // -> Row
.get("magic_value");

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

How to check if an argument of an object is in an ArrayBuffer filled with objects in Scala?

I want to check if an Int typed by an user exists as primary argument/variable(the class has only one argument of type Int) in an ArrayBuffer filled with objects of a class.
It's an assignment for school, and I'm not able to get help of a prof or assistant so I'm asking for your help. I have to code a class "ewallet", which has attributes like "client id"(Int) and "pin code" (random Int between two Numbers). I'm not using "pin code" as an argument of the class as it seems to be implied in the assignment as it says "It has to show the pass when the user creates an account using his client id". I shouldn't be able to create 2 ewallets with the same client id.
So I would have to refuse to create an ewallet when if an ewallet with the same client id exists already in the ArrayBuffer (or array) that stocks ewallets.
Because of the Randomly generated "pin code", it creates different ewallets with same client id and different pin codes. So how to not add an ewallet(class) to a list if an ewallet with some argument exists already?
Thanks for helping a newbie.
I could just created another array list saving the client id's entered by an user and save them to compare with future client id's. But I'd like to learn how to do with an array containing objects.
I tried with for (i <- ListClients) if (NumClient != i.id) but if the list is empty, it doesn't do anything...
class ewallet(clientID: Int){
val id = clientID
val pass = 100 + Random.nextInt((99999-100)+1) //for the class, I didnt include the rest as its not related.
//for the main
def main(args: Array[String]): Unit = {
var ListClients = ArrayBuffer[ewallet]()
var action: Char = " ".charAt(0)
do {
println("[c]-Create ewallet. \n[a]-Access ewallet.\n[q]-Quit")
action = StdIn.readChar()
if (action == 'c') {
val NumClient = StdIn.readLine("Enter your client id :").toInt
var newClient = new ewallet(NumClient)
for (i <- ListClients) if (NumClient == i.id) {
println("Impossible, already exists.")
}
for (i <- ListClients) if (NumClient != i.id){
ListClients += newClient
println("Your pin code is : " + newClient.pass)
}
}
println(ListClients.mkString("\n"))
} while(action != 'q')
I should be able to add newClient to ListClients if NumClient != i.id, but because it's initially empty, it doesn't read those lines… So it does Nothing.
The simplest way would be to assign the result of the presence check to a variable, and add or "not add" the client object based on this variable. In Scala, the idiomatic way to work with collections are their rich set of transformation methods; in your case, exists provides the solution:
val alreadyExists = ListClients.exists(_.id == NumClient)
if (alreadyExists) {
println("Impossible, already exists.")
} else {
ListClients += newClient
println("Your pin code is : " + newClient.pass)
}
If you don't know yet about collection transformations and higher-order functions in general (and you should! they make life a lot easier), then the above piece is actually equivalent to this:
var alreadyExists = false
for (i <- ListClients) {
alreadyExists = alreadyExists || i.id == NumClient
}
(albeit a bit more efficient since it stops the iteration right after the existing client is found, if it is at all present).
As an unrelated comment, in Scala it is conventional to name variables in pascalCase and types in CamelCase. Thus, your class should be called something like EWallet, and variables like ListClients should be called listClients. Also, " ".charAt(0) is the same as ' '.

Groovy/Scala - Abort Early while iterating using an accumulator

I have a fairly large collection that I would like to iterate and find out if the collection contains more than one instance of a particular number. Since the collection is large, i'd like to exit early, i.e not traverse the complete list.
I have a dirty looking piece of code that does this in a non-functional programming way. However, i'm unable to find a functional programming way of doing this (In Groovy or Scala), since I need to do 2 things at the same time.
Accumulate state
Exit Early
The "accumulate state" can be done using the "inject" or "fold" methods in Groovy/Scala but there's no way of exiting early from those methods. Original groovy code is below. Any thoughts?
def collection = [1,2,3,2,4,6,0,65,... 1 million more numbers]
def n = 2
boolean foundMoreThanOnce(List<Integer> collection, Integer n) {
def foundCount = 0
for(Integer i : collection) {
if(i == n) {
foundCount = foundCount + 1
}
if(foundCount > 1) {
return true
}
}
return false
}
print foundMoreThanOnce(collection, n)
One of many possible Scala solutions.
def foundMoreThanOnce[A](collection: Seq[A], target: A): Boolean =
collection.dropWhile(_ != target).indexOf(target,1) > 0
Or a slight variation...
collection.dropWhile(target.!=).drop(1).contains(target)
Scans the collection only until the 2nd target element is found.
Not sure about groovy, but if possible for you to use Java 8 then there is a possibility
collection.stream().filter(z -> {return z ==2;} ).limit(2)
the limit will stop the stream processing as soon as it get 2nd occurrence of 2.
You can use it as below, to ensure there are exact two occurrences
Long occ = collection.stream().filter(z -> {return z ==2;} ).limit(2).count();
if(occ == 2)
return true;

Specman: How to find if a list of bytes exists in another list taking order of the list into account

I have a payload which is a lists of type bytes:
var payload : list of byte;
payload= {1;2;3;4;5;6};
var item1 :list of byte;
item = {3;4;5};
var item2 :list of byte;
item = {1;4};
I would like to implement a code that checks if a list is a sub-list of another. Using "if ..in.." doesn't quite work as it does not take into account the order of the items or if they appear successively or not. I want something that does the following:
if (item1 in payload) ...... should return TRUE. Items exist in payload in the same order.
if (item2 in payload) ...... should return FALSE because although each element in the list exists in the payload, but the item2 elements do not appear successively in the payload list.
Is there an easy way to achieve this? There must be a build -in function in specman for this.
Thanks
The following code should work:
if (item.size()==0) {return TRUE};
for i from 0 to payload.size()-item.size() {
if (item == payload[i..i+item.size()-1]) {
return TRUE;
};
};
return FALSE;
Note that this code is quite expensive memory-wise (the list[a..b] syntax creates a new list every time) so if you have memory considerations it should be modified.