chan11347

chan11347

so i look up the zip(list_of_lists) in github and it have some example

Zips corresponding elements from each list in list_of_lists.
The zipping finishes as soon as any list terminates.

Examples

      iex> List.zip([[1, 2], [3, 4], [5, 6]])
      [{1, 3, 5}, {2, 4, 6}]
      iex> List.zip([[1, 2], [3], [5, 6]])
      [{1, 3, 5}]

i want to make the def function like above

def zip([]), do: []

def zip(list_of_lists) when is_list(list_of_lists) do
    do_zip(list_of_lists, [])
end

i want to understand what is list of lists and how to represent it when every list is not the same, thanks

Showing Posts 1 to 10

lucaong

lucaong

If I understand, you want to reimplement List.zip\1, is that correct? That’s a nice exercise.

The list_of_lists argument is, as the name says, a list of several lists, possibly of different lengths. The zip function iterates through all the lists, grouping the nth element from each list into a tuple. It stops as soon as the shortest list is exhausted.

What exactly you want to understand better? Is something in particular confusing you?

chan11347

chan11347 OP

i am trying to put the code into the exs and run it with erlang

	def cross([]) do
	0
	end

	def cross(list_of_lists) when is_list(list_of_lists) do
    cross(list_of_lists, [])
	end

and the return is said is a undefined function, so i want know is that anything just wrong since i cannot compilation with these code

lucaong

lucaong

Well, there are a number of things that are wrong. First of all, the function must be defined within a module. Second, the recursive call to cross uses the wrong number of arguments (cross is defined with one argument, but is called with two arguments in cross(list_of_lists, [])).

Also, this recursive call would never complete, because the list_of_list is passed unchanged, and therefore will never get to the base case of empty list (unless it’s empty to start with).

Usually, when implementing recursion, you start with a base case, and you make sure that the recursive call moves in the direction of the base case (if the base case is an empty list, the list should be consumed at each recursive call, so that it will eventually be empty).

For example, let’s define a function that takes a list of numbers and returns the sum:

defmodule Sum do
  # Version of sum with one single argument, calling the two
  # arguments version with the initial `partial_sum` of 0
  def sum(list) do
    sum(list, 0)
  end

  # Base case, the given list is empty, so we can just return the
  # sum accumulated so far
  def sum([], partial_sum) do
    partial_sum
  end

  # If the list is not empty, we sum the first element and call
  # the function recursively with the rest of the list, so it shrinks
  # at each call, eventually becoming empty
  def sum([first | rest], partial_sum) do
    sum(rest, partial_sum + first)
  end
end

Now, you can call the defined function:

Sum.sum([1, 2, 3, 4, 5])
#=> 15
chan11347

chan11347 OP

defmodule Ans0 do
	def cross([],[]) do
	0
	end
	
	def cross([h1|t1],[h2|t2]) do
	{h1,h2}
	cross([t1],[t2])
	end

end

so it should be like this?

NobbZ

NobbZ

No.

The {h1, h2} line does not have any effect, its an unused value.

The cross([t1], [t2]) line will eventually just loop forever as cross([[]], [[]]). You do not need to wrap the tails in a list, as they already are lists.

Also your base case will just return 0, which would make your function return 0 regardless of the input, if there wasn’t the infinite loop in the other case. As you want to construct a list in the function, you need to return a list. What do you think how should the return look like?

In the other case, you need to construct the return value from the tuple you already build and forget, and the result of the recursive call. Something like [the_tuple | result_of_the_recursive_call].

lucaong

lucaong

Well, you are making progresses, but there are still things that won’t really work in this code.

First of all, the first definition of cross, for empty lists, returns 0. I don’t know what you are trying to do (are you implementing zip?), but that seems at odd with the rest of the program. What is your expected output? If you are using recursion, your base clause should return that.

Second, the tuple {h1, h2} is created but never used nor returned, so right now it is useless. If you are implementing zip, you’ll want to accumulate these tuples to finally return them in a list.

Remember that Elixir functions always return the result of their last expression.

Also, t1 and t2 are already lists. If you wrap them in brackets you will get nested lists, which is probably not what you want.

Here’s a nudge in the right direction:

defmodule Ans0 do
  # In the public 2 argument version you can call a private
  # 3 arguments version with an added argument to accumulate
  # step by step the final result
  def cross(a, b) do
    cross(a, b, [])
  end

  defp cross([], [], accumulated) do
    # I leave this to you, reason on what must be returned
    # when you reach the base case
  end

  defp cross([head1 | tail1], [head2 | tail2], accumulated) do
    # Here we prepend {head1, head2} to the accumulated
    # result, and pass it with the tails of the lists to the next
    # iteration
    cross(tail1, tail2, [{head1, head2} | accumulated])
  end
end

When implementing it, pay attention to the order of the accumulated list, and also beware that this implementation would only work if the list arguments have the same length. You can add base cases to account for different lengths (I leave this to you).

In general, my recommendation is that you take your time to learn the basics of Elixir before you jump into recursion exercises: it will make it easier to understand why something is not working as it should.

chan11347

chan11347 OP

this is what i try to do about it

chan11347

chan11347 OP

update:

defmodule Ans0 do

	def cross([],[]) do
	end

	def cross([h1|t1],[h2|t2]) do
	[{h1,h2}|cross(t1,t2)]
	end

end
lud

lud

This returns nil, so your final result will be [{'a', 1},{'b', 2}, {'c', 3} | nil] which is called an improper list because it contains a non-list element as the final element (well it is more complicated but I can’t explain it properly).
Note that
[{'a', 1}, {'b', 2}, {'c', 3} | nil]
and
[{'a', 1}, {'b', 2}, {'c', 3}, nil]

are different.

The first one is equivalent to
[{'a', 1} | [{'b', 2} | [{'c', 3} | nil]]]
The second one to
[{'a', 1} | [{'b', 2} | [{'c', 3} | [nil | []]]]]

lucaong

lucaong

You are very close. As @lud explained, you still have an issue with the base case.

In order to solve it for good, think about your base case: if you would call Ans0.cross([], []), what would you expect as a result? Right now, you get nil, but is this what you really should expect? Remember that in Elixir nil is different from [].

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews