Erlang variable pattern matching - sockets

I have a service_echo function in a simple chat application which uses SockJS for implementing multi-user private chat. I created an ETS table for the list of online users. By storing SockJS session, I thought to send message to that Connection whenever I receive a message from a different Connection.
Here is my service_echo code.
service_echo(Conn, {recv, Data}, state) ->
Obj = mochijson2:decode(Data),
{struct, JsonData} = Obj,
Name = proplists:get_value(<<"name">>, JsonData),
A = ets:lookup(username,Name),
io:format("~p",[Conn]),
if
length(A) =:= 0 ->
ets:insert(username,{Name,Conn});
true ->
[{AA,BB}] = ets:lookup(username,Name),
BB:send(Data)
end,
io:format("hello");
Even though Conn and BB are same, still Conn:send(data) sends a valid data to the browser while BB:send(Data) does nothing and even does not show an error.
Since I'm a new to Erlang, please excuse me for any unintented mistakes.

First of all, let me advise you on never using length(A) =:= 0 for testing whether the list A is empty or not; if A a long list, counting its elements will cost you a lot, although the result will not actually be used. Use A =:= [] instead, simpler and better.
I don't understand why you're saying that Conn and BB are the same. This does not follow from the code that you have posted here. If Name is not in the table, you insert an entry {Name, Conn}. Otherwise, if Name exists in the table and is related to a single object BB, you assume that this BB is a module and you call the send function defined therein.
It could be that you're reading wrong the semantics of if --- if that's the case, don't let the true guard confuse you, this is how an if-then-else is written in Erlang. Maybe you wanted to have something like:
...
A = ets:lookup(username,Name),
if
A =:= [] ->
ets:insert(username,{Name,Conn})
end,
[{_,BB}] = ets:lookup(username,Name),
BB:send(Data)
...
or even better:
...
A = ets:lookup(T,Name),
if
A =:= [] ->
ets:insert(T,{Name,Conn}),
BB = Conn;
true ->
[{_,BB}] = A
end,
BB:send(Data)
...
On the other hand, it could be that I misunderstood what you're trying to do. If that's the case, please clarify.

Related

QgsField won't accept parameter typeName

I'm trying to create new vector layer with the same fields as contained in original layer.
original_layer_fields_list = original_layer.fields().toList()
new_layer = QgsVectorLayer("Point", "new_layer", "memory")
pr = new_layer.dataProvider()
However, when I try:
for fld in original_layer_fields_list:
type_name = fld.typeName()
pr.addAttributes([QgsField(name = fld.name(), typeName = type_name)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
I get a layer with no fields in attribute table.
If I try something like:
for fld in original_layer_fields_list:
if fld.type() == 2:
pr.addAttributes([QgsField(name = fld.name(), type = QVariant.Int)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
... it works like charm.
Anyway ... I'd rather like the first solution to work in case if one wants to automate the process and not check for every field type and then find an appropriate code. Besides - I really am not able to find any documentation about codes for data types. I managed to find this post https://gis.stackexchange.com/questions/353975/get-only-fields-with-datatype-int-in-pyqgis where in comments Kadir pointed on this sourcecode (https://codebrowser.dev/qt5/qtbase/src/corelib/kernel/qvariant.h.html#QVariant::Type).
I'd really be thankful for any kind of direction.

Filtering a collection of IO's: List[IO[Page]] scala

I am refactoring a scala http4s application to remove some pesky side effects causing my app to block. I'm replacing .unsafeRunSync with cats.effect.IO. The problem is as follows:
I have 2 lists: alreadyAccessible: IO[List[Page]] and pages: List[Page]
I need to filter out the pages that are not contained in alreadyAccessible.
Then map over the resulting list to "grant Access" in the database to these pages. (e.g. call another method that hits the database and returns an IO[Page].
val addable: List[Page] = pages.filter(p => !alreadyAccessible.contains(p))
val added: List[Page] = addable.map((p: Page) => {
pageModel.grantAccess(roleLst.head.id, p.id) match {
case Right(p) => p
}
})
This is close to what I want; However, it does not work because filter requires a function that returns a Boolean but alreadyAccessible is of type IO[List[Page]] which precludes you from removing anything from the IO monad. I understand you can't remove data from the IO so maybe transform it:
val added: List[IO[Page]] = for(page <- pages) {
val granted = alreadyAccessible.flatMap((aa: List[Page]) => {
if (!aa.contains(page))
pageModel.grantAccess(roleLst.head.id, page.id) match { case Right(p) => p }
else null
})
} yield granted
this unfortunately does not work with the following error:
Error:(62, 7) ';' expected but 'yield' found.
} yield granted
I think because I am somehow mistreating the for comprehension syntax, I just don't understand why I cannot do what I'm doing.
I know there must be a straight forward solution to such a problem, so any input or advice is greatly appreciates. Thank you for your time in reading this!
granted is going to be an IO[List[Page]]. There's no particular point in having IO inside anything else unless you truly are going to treat the actions like values and reorder them/filter them etc.
val granted: IO[List[Page]] = for {
How do you compute it? Well, the first step is to execute alreadyAccessible to get the actual list. In fact, alreadyAccessible is misnamed. It is not the list of accessible pages; it is an action that gets the list of accessible pages. I would recommend you rename it getAlreadyAccessible.
alreadyAccessible <- getAlreadyAccessible
Then you filter pages with it
val required = pages.filterNot(alreadyAccessible.contains)
Now, I cannot decipher what you're doing to these pages. I'm just going to assume you have some kind of function grantAccess: Page => IO[Page]. If you map this function over required, you will get a List[IO[Page]], which is not desirable. Instead, we should traverse with grantAccess, which will produce a IO[List[Page]] that executes each IO[Page] and then assembles all the results into a List[Page].
granted <- required.traverse(grantAccess)
And we're done
} yield granted

How to indiciate a failure for a function with a void result

I have a function in scala which has no return-value (so unit). This function can sometimes fail (if the user provided parameters are not valid). If I were on java, I would simply throw an exception. But on scala (although the same thing is possible), it is suggested to not use exceptions.
I perfectly know how to use Option or Try, but they all only make sense if you have something valid to return.
For example, think of a (imaginary) addPrintJob(printJob: printJob): Unit command which adds a print job to a printer. The job definition could now be invalid and the user should be notified of this.
I see the following two alternatives:
Use exceptions anyway
Return something from the method (like a "print job identifier") and then return a Option/Either/Try of that type. But this means adding a return value just for the sake of error handling.
What are the best practices here?
You are too deep into FP :-)
You want to know whether the method is successful or not - return a Boolean!
According to this Throwing exceptions in Scala, what is the "official rule" Throwing exceptions in scala is not advised as because it breaks the control flow. In my opinion you should throw an exception in scala only when something significant has gone wrong and normal flow should not be continued.
For all other cases it generally better to return the status/result of the operation that was performed. scala Option and Either serve this purpose. imho A function which does not return any value is a bad practice.
For the given example of the addPrintJob I would return an job identifier (as suggested by #marstran in comments), if this is not possible the status of addPrintJob.
The problem is that usually when you have to model things for a specific method it is not about having success or failure ( true or false ) or ( 0 or 1 - Unit exit codes wise ) or ( 0 or 1 - true or false interpolation wise ) , but about returning status info and a msg , thus the most simplest technique I use ( whenever code review naysayers/dickheads/besserwissers are not around ) is that
val msg = "unknown error has occurred during ..."
val ret = 1 // defined in the beginning of the method, means "unknown error"
.... // action
ret = 0 // when you finally succeeded to implement FULLY what THIS method was supposed to to
msg = "" // you could say something like ok , but usually end-users are not interested in your ok msgs , they want the stuff to work ...
at the end always return a tuple
return ( ret , msg )
or if you have a data as well ( lets say a spark data frame )
return ( ret , msg , Some(df))
Using return is more obvious, although not required ( for the purists ) ...
Now because ret is just a stupid int, you could quickly turn more complex status codes into more complex Enums , objects or whatnot , but the point is that you should not introduce more complexity than it is needed into your code in the beginning , let it grow organically ...
and of course the caller would call like
( ret , msg , mayBeDf ) = myFancyFunc(someparam, etc)
Thus exceptions would mean truly error situations and you will avoid messy try catch jungles ...
I know this answer WILL GET down-voted , because well there are too much guys from universities with however bright resumes writing whatever brilliant algos and stuff ending-up into the spagetti code we all are sick of and not something as simple as possible but not simpler and of course something that WORKS.
BUT, if you need only ok/nok control flow and chaining, here is bit more elaborated ok,nok example, which does really throw exception, which of course you would have to trap on an upper level , which works for spark:
/**
* a not so fancy way of failing asap, on first failing link in the control chain
* #return true if valid, false if not
*/
def isValid(): Boolean = {
val lst = List(
isValidForEmptyDF() _,
isValidForFoo() _,
isValidForBar() _
)
!lst.exists(!_()) // and fail asap ...
}
def isValidForEmptyDF()(): Boolean = {
val specsAreMatched: Boolean = true
try {
if (df.rdd.isEmpty) {
msg = "the file: " + uri + " is empty"
!specsAreMatched
} else {
specsAreMatched
}
} catch {
case jle: java.lang.UnsupportedOperationException => {
msg = msg + jle.getMessage
return false
}
case e: Exception => {
msg = msg + e.getMessage()
return false
}
}
}
Disclaimer: my colleague helped me with the fancy functions syntax ...

Resolv::DNS - how do I force TCP?

Does anyone know how do I force TCP when using Resolv::DNS?
It seems that when I ask for ANY records, the output is truncated and I get partial results. When I perform many queries (one for each record type) I get more results. I also get inconsistent results (vary between machines, two sequential queries return different results,...)
I thought it could have something to do with UDP being bounded to packet size.
Any idea how I can force it to use TCP? Any other DNS pakcage that I can use?
I had this same problem, wanting to use Resolv for TCP-only queries as I was expecting result sets that were quite large. I ended up digging through Resolv's source code and learned that, by default, TCP queries are only ever performed if the UDP query fails. I found that I could subclass Resolv::DNS and override the each_resource method. Here's my source:
require 'resolv'
# A TCP-only resolver built from `Resolv::DNS`. See the docs for what it's about.
# http://ruby-doc.org/stdlib-1.9.3/libdoc/resolv/rdoc/Resolv/DNS.html
class TcpDNS < Resolv::DNS
# Override fetch_resource to use a TCP requester instead of a UDP requester. This
# is mostly borrowed from `lib/resolv.rb` with the UDP->TCP fallback logic removed.
def each_resource(name, typeclass, &proc)
lazy_initialize
senders = {}
requester = nil
begin
#config.resolv(name) { |candidate, tout, nameserver, port|
requester = make_tcp_requester(nameserver, port)
msg = Message.new
msg.rd = 1
msg.add_question(candidate, typeclass)
unless sender = senders[[candidate, nameserver, port]]
sender = senders[[candidate, nameserver, port]] =
requester.sender(msg, candidate, nameserver, port)
end
begin # HACK
reply, reply_name = requester.request(sender, tout)
rescue
return
end
case reply.rcode
when RCode::NoError
extract_resources(reply, reply_name, typeclass, &proc)
return
when RCode::NXDomain
raise Config::NXDomain.new(reply_name.to_s)
else
raise Config::OtherResolvError.new(reply_name.to_s)
end
}
ensure
requester.close
end
end
end
Then using it is as easy as follows:
TcpDNS.open :nameserver => ns_addrs, :search => '', :ndots => 1 do |dns|
resp = dns.getresources target, Resolv::DNS::Resource::IN::ANY
end

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.