Saturday, October 25, 2014

Changes 10/23/14 (at NSF meetup) and 10/25/14

NSF Stuff:

  • Kevin showed me a really interesting video where a C# API developer wanted to make his interface very understandable, and to do this was trying to avoid returning null in a method to try to read a string from a file.  He felt that this would be inconsistent with the rest of his interface, as other methods that returned strings were guaranteed to not be null.  
  • He went through various different approaches, which should hold true (to some extent) in any language.
  • What he settled on was returning a Maybe, a collection guaranteed to have either 0 or 1 elements: 0 elements if the file couldn't be read, and 1 if it could, where the element was the string.  This way, he could write code to handle a case with 0 elements much more fluidly than just having a null check.
  • I also learned some stuff about C#!
  • I guess the string data type is a primitive, because it was written as "string" when declaring the return type for his methods.  If my memory is correct, I think you can write it as String as well.
  • I also learned about the out parameter in C#, which was used in one of the approaches to the problem, albeit one that the guy in the video didn't like.  It's still useful to know that you could have a specific variable be modified by a separate method, though.  I think that's pretty cool.

Ruby:

  • Updated code and committed to repo.
  • Fixed ThreadPool#join_all so that it works correctly.
  • Now, when called, it sets the finished flag to true, then does one of two things:
  • If there are still elements in the task queue, Thread#join is called on each of the worker threads.  Since the finish flag is now true, each worker thread continues to work as normal, but will abort once it completes a task and finds the task queue to be empty.  Once all worker threads have completed tasks and found the queue to be empty, the #join_all method will release the lock on the thread it is called in (the main thread, most likely) and the program can continue on.
  • If the task queue is empty when #join_all is called, ThreadPool#kill_all is called, which terminates all worker threads.  This prevents a deadlock where all the threads are waiting on the queue already, and therefore never check to see that the finished flag has been set to true.
  • I also cleaned up some things in the code, and learned some stuff along the way!
  • I had a while loop that was something like
    int i = 0
    while i < 20 do
      ...
      i+=1
    end
    However this is very un-ruby like.  I changed this to be
    20.times do |i| 
      ...
    end
    which is much cleaner and easier to read.  In doing this, I also realized that I had code that read:
    some_integer.times.each_with_index do |i|
    which is just awful. It can be rewritten with the exact same functionality as
    some_integer.times do |i|
    . I'm not sure why I thought I needed to call #each on that, let alone #each_with_index! (If #each is redundant, #each_with_index is doubly redundant because you are already using the integer as an index, so getting the index of that index makes no sense)

1 comment:

  1. Ruby, Java, and now C#, you're becoming a multi-lingual programmer ;-)

    ReplyDelete