Programming thread

B25AF5A9-7ED2-4623-854D-ADE328BEC0EE.gif


No joke, I’m more of a sucker for Pascal. Even if it is old, the way how it’s coded looks nice to me. I’d say this and Perl are the best when learning the language as a hobby, in my opinion.
 
Last edited:
This is probably an elementary question for which I feel obligated to apologize, but I'm not finding an answer in any of my reference materials which is never a good sign. In short, I'm working in Ruby where I want to create a method that can change an arbitrary number of class vars for an instance of a class object by invoking the method along with two sets of params, one being the attrs to change and the other being the new values to use or formula if it's derived data. Kind of like attr_accessor or attr_writer but working on multiple, arbitrary vars so I don't have to 1. repeat myself 2. hardcode which vars are being changed. Once that's figured out I'd also like to be able to abstract it out a little further so that I can change how it's invoked in an extensible fashion.
For example if I have a People class with say, @Name, @job_title, @department, @salary, @boss, @subbordinates, @guid class vars how can I call a single method to at one time change @salary, @boss, @job_title one time, and another @Name, @guid, or the like, and then once that's done abstract it out so I can invoke say,
bob = People.new(...) these_vars_to_change = [...] engineering_vars = [...] marketing_vars = [...] which_vars_to_change = 'marketing' bob.change_many_vars(these_vars_to_change, 'which_vars_to_change'_vars) # This part would be handled by flow control. which_vars_to_change = 'engineering' bob.change_many_vars(these_vars_to_change, 'which_vars_to_change'_vars)
In both the first and second, more abstract case the issue I'm running into is that any vars I pass in are either hardcoded and therefore useless or interpreted as a string literal and therefore useless. I don't like being spoonfed, but the fact that I'm not turning up anything on what should be such an obviously essential tool means I must be missing something fundamental.
Is this your brain on OOP?

You're seriously creating accessor methods to set internal variables? You don't see the problem with this?

As for your actual question - I don't know Ruby, but isn't there some way to access the object as a dictionary/hashmap? That's how they do it in Python, at least.
 
  • Feels
Reactions: Knight of the Rope
In short, I'm working in Ruby
Yikes.

I want to create a method that can change an arbitrary number of class vars for an instance of a class object by invoking the method along with two sets of params, one being the attrs to change and the other being the new values to use or formula if it's derived data.
What, you mean something like this? e.g. creating and removing instance variables at runtime fucking hell man people are right about us OOP speds
Ruby:
my_object = Object.new
my_object.instance_variable_set(:@new_var, 'value')  #=> "value"
my_object.inspect                                    #=> "#<Object:0x00005573bffa13a0 @new_var=\"value\">"
my_object.remove_instance_variable(:@new_var)        #=> "value"
my_object.inspect                                    #=> "#<Object:0x00005573bffa13a0>"
And then just write a method that maps that over a given pair of arrays or a hash or something you goddamned degenerate.
 
  • Feels
Reactions: Coffee Shits
This is probably an elementary question for which I feel obligated to apologize, but I'm not finding an answer in any of my reference materials which is never a good sign. In short, I'm working in Ruby where I want to create a method that can change an arbitrary number of class vars for an instance of a class object by invoking the method along with two sets of params, one being the attrs to change and the other being the new values to use or formula if it's derived data. Kind of like attr_accessor or attr_writer but working on multiple, arbitrary vars so I don't have to 1. repeat myself 2. hardcode which vars are being changed. Once that's figured out I'd also like to be able to abstract it out a little further so that I can change how it's invoked in an extensible fashion.
For example if I have a People class with say, @Name, @job_title, @department, @salary, @boss, @subbordinates, @guid class vars how can I call a single method to at one time change @salary, @boss, @job_title one time, and another @Name, @guid, or the like, and then once that's done abstract it out so I can invoke say,
bob = People.new(...) these_vars_to_change = [...] engineering_vars = [...] marketing_vars = [...] which_vars_to_change = 'marketing' bob.change_many_vars(these_vars_to_change, 'which_vars_to_change'_vars) # This part would be handled by flow control. which_vars_to_change = 'engineering' bob.change_many_vars(these_vars_to_change, 'which_vars_to_change'_vars)
In both the first and second, more abstract case the issue I'm running into is that any vars I pass in are either hardcoded and therefore useless or interpreted as a string literal and therefore useless. I don't like being spoonfed, but the fact that I'm not turning up anything on what should be such an obviously essential tool means I must be missing something fundamental.
Bruh, why would you not just use a map/dictionary at that point. What's in your software architecture that's requiring you to be able to batch-change dynamically created member variables?
Is this for serialization?
 
  • Feels
Reactions: GreeneCoDeputy
What, you mean something like this? e.g. creating and removing instance variables at runtime fucking hell man people are right about us OOP speds
Ruby:
my_object = Object.new
my_object.instance_variable_set(:@new_var, 'value')  #=> "value"
my_object.inspect                                    #=> "#<Object:0x00005573bffa13a0 @new_var=\"value\">"
my_object.remove_instance_variable(:@new_var)        #=> "value"
my_object.inspect                                    #=> "#<Object:0x00005573bffa13a0>"
And then just write a method that maps that over a given pair of arrays or a hash or something you goddamned degenerate.
Not that bad. I don't want to dynamically add and remove variables themselves, just their values. So in the first form
Ruby:
class People
    def initialize(name, job_title, department, salary, boss, subordinates)
    @name = name
    (...)
    @subordinates = subordinates
end
bob = People.new("bob", "wagie", "facilities", 10, "PHB", [])
If Bob gets a promotion using attr_writer or attr_accessor I have to type out
Ruby:
bob.job_title = "senior wagie"
bob.salary = 11
which gets to be cumbersome if I'm changing many at a time. I'm trying to figure out how to do something like
Code:
bob.change_many_vars("@job_title", "@salary", "senior wagie", 11)

In the second form I'd want to abstract it out to prefab templates I can use so I can define, say
Ruby:
bob = People.new
promotion_vars = ["@job_title", "@department", "@salary", "@boss"]      # Maybe hashes are better than arrays for this, idk.
engineering_promotion = ["code monkey", "engineering", 100, "PHB"]
marketing_promotion = ["pro liar", "marketing", 100, "VP of lying"]
bob.change_many_vars(promotion_vars, engineering_promotion)
So you can see there's no addition or deletion going on, only alteration. The biggest problem is that unquoted the instance vars are read as the the values themselves and therefore in the first form with bob I'm changing the "@job_title" string object to "senior wagie" rather than @job_title itself. Unquoted I'm changing "wagie" to "senior wagie", but bob.@job_title remains unchanged, still "wagie". Same problem in the second form. I could of course try to kludge around this by writing class methods hardcoded each to change an exact set of instance variables so I can call
bob.change_jobtitle_department_salary(engineering_promotion[0], engineering_promotion[1], engineering_promotion[2])
which it feels like I'm being steered towards, but I'm sure I don't have to explain why that's a terrible idea.
Bruh, why would you not just use a map/dictionary at that point. What's in your software architecture that's requiring you to be able to batch-change dynamically created member variables?
Is this for serialization?
Wouldn't I still have the same problem if I did?
 
  • Thunk-Provoking
Reactions: albert chan
So you can see there's no addition or deletion going on, only alteration.
You can still use instance_variable_set though, right? e.g. something like this?
Ruby:
class People
  attr_accessor :name, :job_title, ..., :subordinates
 
  def initialize(name=nil, job_title=nil, ..., subordinates=nil)
    @name = name
    @job_title = job_title
    ...
    @subordinates = subordinates
  end
 
  def change_many_vars(vars_to_change, new_values)
    vars_to_change.zip(new_values).to_h.map do |var, value|
      self.instance_variable_set(var, value)
    end
  end
end

bob = People.new
bob.inspect    #=> "#<People:0x000056469a0cc6a0 @name=nil, @job_title=nil, ..., @subordinates=nil>"
bob.job_title  #=> nil

promotion_vars = ["@job_title", "@department", "@salary", "@boss"]
engineering_promotion = ["code monkey", "engineering", 100, "PHB"]

bob.change_many_vars(promotion_vars, engineering_promotion)
bob.inspect    #=> "#<People:0x000056469a0cc6a0 @name=nil, @job_title=\"code monkey\", ..., @subordinates=nil>"
bob.job_title  #=> "code monkey"

Then you have a class method that lets you change as many of the instance variables as you want all at once (and also lets you create/overwrite private instance variables at will, so it's still degeneracy. But whatever works).
 
So you can see there's no addition or deletion going on, only alteration. The biggest problem is that unquoted the instance vars are read as the the values themselves and therefore in the first form with bob I'm changing the "@job_title" string object to "senior wagie" rather than @job_title itself. Unquoted I'm changing "wagie" to "senior wagie", but bob.@job_title remains unchanged, still "wagie". Same problem in the second form. I could of course try to kludge around this by writing class methods hardcoded each to change an exact set of instance variables so I can call
bob.change_jobtitle_department_salary(engineering_promotion[0], engineering_promotion[1], engineering_promotion[2])
which it feels like I'm being steered towards, but I'm sure I don't have to explain why that's a terrible idea.

Wouldn't I still have the same problem if I did?
When I run into an issue that seems like I'm using my face as one of those ice-breaking ships they use above the Arctic Circle, I try to back off a bit and question whether the resistance I'm running into is because I'm simply conceptualizing the problem and/or solution incorrectly.

At a glance, this strikes me as the kind of issue that you see when you're trying to do this at the wrong level in the architecture.

For example, why does the method take two collections of arbitrary length? Why aren't the key and value in the same data structure? Having them separate seems to be inviting disaster if the indexes get messed up.

The overhead of maintaining the field names with the values should be minimal even for fairly large sets of data.

Usually when I see this type of thing it's because someone wants to make some kind of dynamically-generated editing UI on the front end based on a set of classes. In Python this task is pretty straight forward and in C#/.NET we lean heavily on reflection so the implementation is far from the individual class definitions.
 
  • Like
Reactions: Coffee Shits
Every time I hear that this or some other language finally introduces type hinting (or annotations, or whatever you want to call them) I think to myself - what the fucking fuck? So after 20-30 years of excruciating pain they (language maintainers and toolchain developers) are FINALLY admitting that these greybeard wackos mumbling something in the corner about "type safety" might have actually had some good reasons? Well, imagine my shock!

I fucking love hearing about all these failed experiments - Lua, PHP, Python, whatever else - how they finally come to drop the pretense of dynamicness being the bestest feature no srsly guis, we're not some poo-poo "static" thing lol who wants to be "static" in a dynamic and fluid XXI century oh my god why do I have 20 GiB of stacktraces in my server log...

Obviously, some batshit insane nutjob will soon develop a new, "fully dynamic BUT SAFE (no really, trust me!)" language in a rebellion against this ossified and "static" and "obsolete" technologies. And if it gains any traction, the same story will repeat itself 20-30 years down the road.

Just as (fr)agile development methodology is rediscovered over and over, with progressively more depressing results.

It's worth noting that at least in a large part, the motivation for adding type hints into Python was for better autocompletion in IDE's. Previously, some IDE's would make use of docstrings to propagate typing information for autocomplete (quite useful for new libraries or if you're lazy), as well as to show possible errors, but docstrings aren't a set format and it was a bit janky at times. The typing stuff doesn't really effect execution, if you give the wrong type to a function the Python interpreter isn't going to complain, but the IDE or linter will. Being an autist myself I just like to clearly define what goes in and out of different functions regardless of language, makes it feel more structured, but most of the time type hinting is a convenience thing for maintainers and IDE's, and rarely actually introduces type safety.

Regardless of this, I do think Python is ill-suited for any sort of software that is mission critical or something that needs to be kept maintained for an extended period of time, C or C++ are your go to for those situations. Python is great for banging out a quick script or library to do something, and it's pretty nice for data science. It's also good for dealing with abstract and unusual situations, the class system in Python is typically easier to bend to your needs than C++, although you could certainly do it in either. C is nice for it's simplicity, but becomes a pain when OOP becomes reasonable, you can do it, but it's generally more of a pain to implement.
 
I was going to complain about Python being a piece of shit but then I remembered PowerShell exists.

PowerShell seems pretty good at first but god damn it has so many stupid issues, take Invoke-Command as an example, when an error occurs its default action is to spit out a stacktrace but not actually throw an exception so if you use a try-catch block, the catch won't ever run unless you specify "-ErrorAction Stop". What really pisses me off is these gotchas are only something you find out after trying to run the piece of shit.

Also PowerShell seems to be engineered for smooth brained retards. How fucking hard is it to understand what a type is? Why does it default to allowing you to access uninitialized variables with NO warning? Unbelievable. I also hate the only "good" editor is VS Code.

Give me C# or give me death.
 
  • Like
Reactions: Strange Looking Dog
How fucking hard is it to understand what a type is? Why does it default to allowing you to access uninitialized variables with NO warning?
Unix shell variables don't have types (or maybe it's better to say everything is a string) and let you access uninitialized variables (as in echo $farts, which just prints an empty string) so maybe they're just following its lead. Seeing as how PowerShell was trying to be a step up from Unix shells, though (from what I remember; I've never used it but I remember reading about it and thinking it had some good ideas), I guess it's too bad they didn't take the initiative to improve those sorts of things.

YouTube recommended this video comparing ARM and RISC-V architectures to me, and it's pretty interesting. It's pretty much just a slideshow so I recommend putting it on while you do chores or something if you want to watch it.


I'll tl;dw what I think are the most interesting bits: The ISA of RISC-V is very bare bones with features which are common in other chipsets, such as multiplication and division, actually implemented with extensions. While I suppose this is great for ensuring your architecture can work in dollar-store wristwatches as well as workstations and servers, it also means that there's potential for a wide range between two chips of the same "generation" in terms of what functionality they actually support. To complicate that, manufacturers can also implement their own proprietary extensions, so there's potential for a case like the MMX debacle back in the early Pentium days where a leading manufacturer implements their own extensions which other manufacturers cannot legally implement themselves (or only can after paying a licensing fee) and software developers might choose to support at the cost of their software not running as well on competitors' chips if it runs at all. ARM on the other hand does not allow for such extensions and you have a greater guarantee that a chip from Apple, Qualcomm, or Samsung from the same "generation" will have the same functionality.

Also, RISC-V chips are currently not nearly competitive with ARM chips in terms of power per dollar. The gap may narrow if RISC-V sees wider adoption, but given that ARM has a huge head start in terms of real-world usage and is currently in all sorts of devices whereas RISC-V is still something of a curiosity, I foresee ARM retaining a huge lead in terms of R&D teams working on implementing and improving it for the near future.
 
  • Like
Reactions: Strange Looking Dog
I'll tl;dw what I think are the most interesting bits: The ISA of RISC-V is very bare bones with features which are common in other chipsets, such as multiplication and division, actually implemented with extensions. While I suppose this is great for ensuring your architecture can work in dollar-store wristwatches as well as workstations and servers [you point out the ecosystem mess this can result in].
One of the single most important requirements of the ISA is that students can implement a bare bones version of it in a semester. This plus arguments about complexity when you try to make it fast is one reason it doesn't have CPU status flags, one excuse for not making it easy to detect anything but divide by zero is that "C and Java don't care." People who want to write correct software, and the cryptography community that needs to work with long integers are not pleased.
Also, RISC-V chips are currently not nearly competitive with ARM chips in terms of power per dollar....
That's a reflection of its relatively immature state, ARM is 36 years old, RISC-V only 11, and it took a long time for ARM to get big and then huge. If RISC-V gets popular enough power/dollar will probably fix itself. Meanwhile a variety of major users of embedded chips like Western Digital are or have moved to it to avoid paying the "ARM tax."
 
You can still use instance_variable_set though, right? e.g. something like this?
Ruby:
class People
  attr_accessor :name, :job_title, ..., :subordinates
 
  def initialize(name=nil, job_title=nil, ..., subordinates=nil)
    @name = name
    @job_title = job_title
    ...
    @subordinates = subordinates
  end
 
  def change_many_vars(vars_to_change, new_values)
    vars_to_change.zip(new_values).to_h.map do |var, value|
      self.instance_variable_set(var, value)
    end
  end
end

bob = People.new
bob.inspect    #=> "#<People:0x000056469a0cc6a0 @name=nil, @job_title=nil, ..., @subordinates=nil>"
bob.job_title  #=> nil

promotion_vars = ["@job_title", "@department", "@salary", "@boss"]
engineering_promotion = ["code monkey", "engineering", 100, "PHB"]

bob.change_many_vars(promotion_vars, engineering_promotion)
bob.inspect    #=> "#<People:0x000056469a0cc6a0 @name=nil, @job_title=\"code monkey\", ..., @subordinates=nil>"
bob.job_title  #=> "code monkey"

Then you have a class method that lets you change as many of the instance variables as you want all at once (and also lets you create/overwrite private instance variables at will, so it's still degeneracy. But whatever works).
This looks a lot like what I want, and thanks for saving me tens of man hours. But to a more open ended question everyone's calling me a degenerate for trying to create an interface that does attr_writer for n instance variables at a time rather than just one, which seems like a logical jump to me. Clearly I'm missing a fundamental piece of theory and if anyone can tell me what that is, or better yet name/linkdrop a book on theory or a rant from some 80s revolutionary on The Right Way that'd be appreciated. Now that I know how to catch a fish, it's probably important to figure out why everyone says the fish I'm seeking are all diseased and radioactive.
 
But to a more open ended question everyone's calling me a degenerate for trying to create an interface that does attr_writer for n instance variables at a time rather than just one, which seems like a logical jump to me.
It's more the whole 'doing it dynamically at run-time' that's the issue.

If you want to (statically) do attr_writer for multiple attributes at a time it's easy. e.g. here's me doing it for one variable:
Ruby:
attr_writer :one
and look at me go! Here's me doing it for three:
Ruby:
attr_writer :one, :two, :three
Sure that's compile-time declaration, but why wouldn't that be sufficient? The only case I can think of where you'd want a separate interface is if you were planning on adding instance variables on-the-fly during program execution. Which is 'bad' in the sense that it kind of defeats the point of having the class-object scaffolding at all (i.e. if you knew you'd have to add those instance variables in later, then why not just add them from the start? And if your answer is that you don't know them from the start, for example because the user adds them in later, then you see the design/security issues with that too, right?)

That aside, to guide you on your path of degeneracy, it's worth noting that Ruby has the absolutely haram concept of reopening a class to add shit into it later. So actually you can just do this:
Ruby:
class Foo
  def initialize(bar)
    @bar = bar
  end
end

x = Foo.new(7)
x.bar  #-> NoMethodError

class Foo
  attr_accessor :bar
end
x.bar  #=> 7

Or more succinctly and 'map'ably, this:
Ruby:
class Foo
  def initialize(bar)
    @bar = bar
  end
end

x = Foo.new(8)
x.bar  #=> NoMethodError

Foo.class_eval{attr_accessor :bar}
x.bar  #=> 8

This is heresy.
 
It's more the whole 'doing it dynamically at run-time' that's the issue.

If you want to (statically) do attr_writer for multiple attributes at a time it's easy. e.g. here's me doing it for one variable:
Ruby:
attr_writer :one
and look at me go! Here's me doing it for three:
Ruby:
attr_writer :one, :two, :three
Sure that's compile-time declaration, but why wouldn't that be sufficient? The only case I can think of where you'd want a separate interface is if you were planning on adding instance variables on-the-fly during program execution. Which is 'bad' in the sense that it kind of defeats the point of having the class-object scaffolding at all (i.e. if you knew you'd have to add those instance variables in later, then why not just add them from the start? And if your answer is that you don't know them from the start, for example because the user adds them in later, then you see the design/security issues with that too, right?)
I don't know if it changes anything, but I should probably clarify that I mean condensing
Ruby:
Foo.one = 1
Foo.two = 'deux'
Foo.three = 11
into a single statement after object Foo's already created, which I think is covered by the aforementioned instance_variable_set.
 
  • Like
Reactions: Knight of the Rope
I don't know if it changes anything, but I should probably clarify that I mean condensing
Ruby:
Foo.one = 1
Foo.two = 'deux'
Foo.three = 11
into a single statement after object Foo's already created, which I think is covered by the aforementioned instance_variable_set.

In Rails there's the "update" method that does what you want. I don't think there's a way to cleanly do it on ordianry objects though. You can make a function that loops through a given hashmap and uses "instance_variable_set" on the object, but that will break any encapsulation (bypassing setters etc).
 
In Rails there's the "update" method that does what you want. I don't think there's a way to cleanly do it on ordianry objects though. You can make a function that loops through a given hashmap and uses "instance_variable_set" on the object, but that will break any encapsulation (bypassing setters etc).
Not to shittalk advice but isn't rails used near exclusively for the cancer that is """""web development""""" and comes with a code of conduct?
 
  • Like
Reactions: hundredpercent
Not to shittalk advice but isn't rails used near exclusively for the cancer that is """""web development""""" and comes with a code of conduct?
The more high-level the language is, the more trannies and web developers (but I repeat myself) it has. Only exception being the hardcore functional languages, of course.

That's why they created Go and Rust, so they could have a tranny-infested low-level language. Hardly any C projects have a CoC; nearly all Go/Rust projects do.
 
Not to shittalk advice but isn't rails used near exclusively for the cancer that is """""web development""""" and comes with a code of conduct?
Yes but a) most big software projects have a CoC now; they're practically inescapable and b) the only reason most people use Ruby nowadays is for Rails webdev, so I assumed that's what you were doing too.
 
Back