Follow Slashdot stories on Twitter

 



Forgot your password?
typodupeerror
×
Security

4 Tips For Your New Laptop 310

Bennett Haselton writes with four big tips for anyone blessed by the holiday buying frenzy with a new laptop; in particular, these are tips to pass on to non-techie relatives and others who are unlikely to put (say) "Install a Free operating system" at the very top of the list: Here's Bennett's advice, in short: (1) If you don't want to pay for an anti-virus program, at least install a free one. (2) Save files to a folder that is automatically mirrored to the cloud, for effortless backups. (3) Create a non-administrator guest account, in case a friend needs to borrow the computer. (4) Be aware of your computer's System Restore option as a way of fixing mysterious problems that arose recently." Read on for the expanded version; worth keeping in mind before your next friends-and-family tech support call.

Comment Re:JSON (Score 1) 112

It doesn't require all those extras brackets and braces and quotes.

My point is all those extra brackets, braces, and quotes (and field labels) don't cost you much. They compress efficiently.

JSON is like any hammer. Sometimes you gotta know when it's time to put it down and pick up the screwdriver instead.

No argument there - JSON isn't my only tool. :) I just disagree that it "fails hard when you want to send 1,000s of records".

Comment Re:JSON (Score 1) 112

Sending 1,000 copies of that is going to take a lot more packets than a fixed binary format where you can pack the entire thing down to 9 bytes e.g. 8 bytes for the Id, and both bools into a bitset on the last byte.

That's why you compress the stream. HTTP supports Content-Encoding: gzip, or you can wrap it around your file format on disk. Here's what happens with your example:

user@host:~$ ruby <<EOF | gzip | wc -c
prng = Random.new
1000.times do |i|
    puts <<EOR
{
            CustomerId: "#{prng.bytes(8).unpack('H*').first}",
            AllowExtendedConfiguation: "#{prng.rand(2).zero? ? 'true' : 'false'}",
            IsMaximumLengthRequired: "#{prng.rand(2).zero? ? 'true' : 'false'}"
},
EOR
end
EOF
12550

12550 bytes... 12.5 bytes per record, instead of your hand-optimized 9 bytes per record. I'm only paying a 28% premium with 100% random data. When it contains text strings (and we're talking about Wave here - it's mostly text) it's quite common for gzipped JSON to be smaller than an optimized but uncompressed binary format.

This frequently happens even with raw numbers. You won't have 4 billion customers for a while, so let's make the first four bytes of the CustomerId all zeroes:

CustomerId: "00000000#{prng.bytes(4).unpack('H*').first}",

I now have 7.5 bytes per record. I'm already doing better than your binary format, unless you plan to do variable length encoding on the customer ID. That'd be even more code you have to write and debug.

There are certainly cases where shaving off the last few bytes might be worthwhile, but for the general internet, and for the kind of uses that Wave is meant for... no. The simpler code (not inventing a new serialization format) and debugging advantages of human-readable streams outweigh the marginal bandwidth savings of a binary protocol.

Comment Re:Trendy no more? (Score 4, Informative) 65

I've used both a fair bit. They are similar in many ways so it's mostly a matter of preference.

I've found Ruby makes it easy to explore objects and see what can be done with them. The consistent OO model makes it easy to perform concise data manipulation. Here's a quick example:


irb(main):001:0> arr = ["1", "2", "3", "4"]
=> ["1", "2", "3", "4"]
irb(main):002:0> arr.methods - Object.methods
=> [:to_a, :to_ary, :[], :[]=, :at, :fetch, :first, :last, :concat, :>>, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each, :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!, :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if, :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear, :fill, :slice, :slice!, :assoc, :rassoc, :+, :*, :-, :&, :|, :uniq, :uniq!, :compact, :compact!, :flatten, :flatten!, :count, :shuffle!, :shuffle, :sample, :cycle, :permutation, :combination, :repeated_permutation, :repeated_combination, :product, :take, :take_while, :drop, :drop_while, :bsearch, :pack, :entries, :sort_by, :grep, :find, :detect, :find_all, :flat_map, :collect_concat, :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?, :min, :max, :minmax, :min_by, :max_by, :minmax_by, :member?, :each_with_index, :each_entry, :each_slice, :each_cons, :each_with_object, :chunk, :slice_before, :lazy]
irb(main):003:0> arr.pop
=> "4"
irb(main):004:0> arr.join
=> "123"
irb(main):005:0> arr.map { |i| i.to_i }
=> [1, 2, 3]
irb(main):006:0> arr.map(&:to_i).reduce(&:+)
=> 6

Here's the same thing in Python:


In [1]: arr = ["1", "2", "3", "4"]

In [2]: dir(arr)
Out[2]:
[(stuff removed, fucking lameness filter) 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

In [3]: arr.pop()
Out[3]: '4'

OK, it's pretty similar so far, but then we want to join the array. OO came late to Python, so while some things are implemented as methods on the array, a lot of things are functions which operate on an array. As such, they don't appear on the list above. Bizarrely, it's a method on string acting as a function on an array:


In [4]: "".join(arr)
Out[4]: '123'

Perhaps that's intuitive to someone, but to me, they took join which is a natural thing to do to an array and put it somewhere else so I had to look it up in the docs.

The list comprehension handles the simple mapping okay:


In [5]: [int(i) for i in arr]
Out[5]: [1, 2, 3]

But the map-reduce example gets messy:


In [6]: reduce(lambda x, y: x+y, map(int, arr), 0)
Out[6]: 6

Speaking of lambdas, Ruby makes this convenient:


irb(main):001:0> def retry_loop(tries)
irb(main):002:1> yield
irb(main):003:1> rescue
irb(main):004:1> retry if (tries -= 1) > 0
irb(main):005:1> end
=> nil
irb(main):006:0> retry_loop(3) { puts "failing"; raise }
failing
failing
failing
=> nil
irb(main):007:0> retry_loop(3) { puts "succeeding" }
succeeding
=> nil

Doing this in Python is miserable: http://code.activestate.com/recipes/578163-retry-loop/

Another difference is namespacing. Ruby imports libraries as classes or extensions to classes. Python imports them selectively into the global namespace. Python's finer grained control helps mitigate the collisions this causes, but it means that every Python script has to start with a long list of imports. Ruby can include a lot by default because all the additions are neatly contained in a class.

Python's docs are verbose and comprehensive, like a full manual. Ruby's docs tend to be concise and somewhat incomplete, like a reference guide. Take a read through these and see how long it takes you to figure out how to simply start a thread in each language:
http://docs.python.org/3/library/threading.html
http://www.ruby-doc.org/core-2.1.0/Thread.html

Both styles have their place, but I like that I can get the reference guide by just googling a feature. Python doesn't really have the short form. On the other hand, the full manual for Ruby will set you back $28: http://pragprog.com/book/ruby4/programming-ruby-1-9-2-0

Python has a thing: "There should be one -- and preferably only one -- obvious way to do it". This is a good philosophy to keep the language clean, but sometimes it means they don't provide some functionality since it's supposed to be obvious how to do it yourself. And thus, it's self-defeating: http://tomayko.com/writings/cleanest-python-find-in-list-function . In Ruby, it's simple:


irb(main):007:0> arr.grep(/[12]/)
=> ["1", "2"]
irb(main):008:0> arr.grep(/[12]/).first
=> "1"

And having simple things BE simple makes it really easy to go exploring. Hey look, here are all the methods on an array which return a boolean, or which cast it to another class:


irb(main):014:0> arr.methods.grep(/\?/)
=> [:frozen?, :eql?, :empty?, :include?, :all?, :any?, :one?, :none?, :member?, :nil?, :tainted?, :untrusted?, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :respond_to?, :equal?]
irb(main):015:0> arr.methods.grep(/to_/)
=> [:to_s, :to_a, :to_ary, :psych_to_yaml, :to_yaml, :to_yaml_properties, :to_enum]

I could go on, but perhaps this gives you some idea. I'm focusing a lot on where I think Ruby has things right (since you asked), but they're both well designed languages with many similarities. Ruby is a carefully self-consistent language which encourages concise but semantic style. Python is an evolved and quite complete language which encourages verbose but readable style.

I personally find Ruby cleaner, easier to navigate, and more intuitive, and the docs are easier to read. For me that makes it faster, more fun, and less frustrating. YMMV.

Comment Re:The thousand words I saw (Score 4, Informative) 65

TFA describes it in a way that makes sense even if it's technically inaccurate:

The water drops are so tiny they don't have any moisture in them; you can test it on paper or your glasses -- your piece of paper will remain dry and your glasses won't steam up.

More accurately: The water drops are so tiny they won't moisten things they contact.

... let's call a recess and re-convene when that statement makes sense, shall we?

You may now resume bashing the gizmo for being inadequate instead of the submitter for being incomprehensible or the editors for being incompetent.

Comment Re:Watch out (Score 2) 99

That's less than 5x the distance.

It's much closer than that: the moon is only another 70% delta-v from LEO. http://en.wikipedia.org/wiki/Delta-v_budget

Unfortunately it's not just a linear extrapolation. The Merlin engine burns kerosene with liquid oxygen. That's a good setup to get to LEO, but upper stages have more engineering constraints (starting after coasting for several days in vacuum; cryogenic fuels boil off; trying to squeeze more specific impulse where it really pays off), so they tend to run on hydrazine. It requires a whole new design, whereas the Falcon has simply been scaled up.

I don't know that much about the business, but generally there's a lot of money in getting to LEO, and not a lot of commercial interest in the moon. I don't foresee SpaceX dumping the money into such a design any time soon. If someone does want to get to the moon it's more likely they'd build a specialized spacecraft and then pay SpaceX for a ride to LEO.

Comment Re:House of Cards (Score 1) 276

not killing dictators is actually important because if killing them is the only way to get rid of them they will hold on more tightly. The means of bribing them by letting them keep some ill-gotten gains is justified by the ends

Putting aside the moral argument, I disagree with the practical effect. Providing a way out might encourage the current tyrant to retire peacefully, but it also makes the position more appealing to the next ten guys who want to take his place.

Comment Re:missing the point (Score 5, Informative) 173

its widely recognized that US beat the Soviets in the early space race

By whom?

First artificial satellite: Sputnik
First human in space: Yuri Gagarin
First human in orbit: Yuri Gagarin (He gets mentioned twice because he achieved this before the US managed even a suborbital flight)
First lunar flyby: Luna 1
First impact on the moon: Luna 2
First spacewalk: Aleksei Leonov
First soft landing on the moon: Luna 9

The commitment to boots on the moon led to Gemini turning things around in the mid '60s, but before that the Soviets did quite well, especially with Earth-orbit tech.

Comment Re:That's why (Score 1) 961

Coke is a poor choice. You'll die of a heart attack or stroke, and you'll be agitated and panicking the whole way down. It will be painful for both you and the family member who gives it to you.

Opiates (heroin or morphine) or barbiturates (anything ending in -barbital) are better. You will be instantly comfortable, unconscious shortly thereafter, and you'll die of respiratory depression in your sleep which is peaceful and much less traumatic for anyone who's with you.

Slashdot Top Deals

If all else fails, lower your standards.

Working...