Двойной ParamArray

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Двойной ParamArray

Сообщение Amed » 03.03.2005 (Чт) 1:19

Необходим вызов двух функций - одна передаёт в другую переданный её в свою очередь массив параметров.
Есть код:
Код: Выделить всё
Private Sub Form_Load()
Call EQ("1", "2")
End Sub

Private Sub EQ(ParamArray PA())
Dim tmp

For Each tmp In PA
    Action (PA)
Next tmp
End Sub

Private Function Action(ParamArray PA2()) As Variant
Dim tmp2

For Each tmp2 In PA2
    MsgBox tmp2
Next tmp2
End Function


Вызывает ошибку Type Mismatch (попробуйте сами).

Решение достаточно просто создаём доп. переменную, присваиваем ей переданный массив (причём след. функцию можно вызывать как обычно (!!!), - передавая ей не tmpA, а PA):
Код: Выделить всё
Private tmpA()

Private Sub Form_Load()
Call EQ("1", "2")
End Sub

Private Sub EQ(ParamArray PA())
Dim tmp

For Each tmp In PA
    tmpA = PA
    Action (tmpA)

    'Всё работает, даже если вызывать
    'Action (PA) (!!!)
Next tmp
End Sub

Private Function Action(ParamArray PA2()) As Variant
Dim tmp2

For Each tmp2 In tmpA
    MsgBox tmp2
Next tmp2
End Function


Вопрос:
а) почему возникает ошибка
б) как избавиться от неё (если это возможно). Хотелось бы "полноценно" вызывать две вложенные функции с ParamArray (без дополнительных массивов)

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.03.2005 (Чт) 3:25

Потому что нефиг заключать аргумент в скобки, когда возвращаемое значение не используется...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.03.2005 (Чт) 3:41

Не понял...
Код: Выделить всё
Action (PA)

заменять на
Код: Выделить всё
Action PA

? Всё то же самое, нет разве?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.03.2005 (Чт) 5:02

Нет разве :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 5:03

Отвечаю в обратном порядке :)

Во втором примере у тебя все работает потому, что у тебя там ошибка (прикольно звучит :) ) Ошибка такая :
Private tmpA()

Private Sub Form_Load()
Call EQ("1", "2")
End Sub

Private Sub EQ(ParamArray PA())
Dim tmp

For Each tmp In PA
tmpA = PA
Action (tmpA)

'Всё работает, даже если вызывать
'Action (PA) (!!!)
Next tmp
End Sub

Private Function Action(ParamArray PA2()) As Variant
Dim tmp2

For Each tmp2 In tmpA
MsgBox tmp2
Next tmp2
End Function

Ты передаешь функции Action "ParamArray PA2()", однако внутри используешь tmpA Работай внутри функции с РА2 и снова получишь свою любимую ошибку "Несоответствие типов"

Теперь по первому примеру : тоже все прозрачно... Посмотри мой код, сравни со своим и поймешь, почему у тебя несоответствие типов. Подсказка выделена красным.
Код: Выделить всё
Option Explicit

Private Sub Form_Load()
   
    Call EQ("1", "2")
   
End Sub

Private Sub EQ(ParamArray PA())
   
    Dim tmp

    For Each tmp In PA
        Action (PA)
    Next tmp
   
End Sub

Private Sub Action(ParamArray PA2())
   
    Dim tmp2
    Dim tmp3

    For Each tmp2 In PA2
        For Each tmp3 In tmp2
            MsgBox CStr(tmp3)
        Next tmp3
    Next tmp2
   
End Sub


.For Each tmp2 In PA2
....For Each tmp3 In tmp2
.......MsgBox CStr(tmp3)
....Next tmp3

.Next tmp2

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.03.2005 (Чт) 5:20

Ы-ы-ы! Вот она, польза ночного кодинга! :D

Низя было сразу сказать, в чём дело? ;)
*Тема закрыта*

Спасибо, GSerg, спасибо, vvs_adm!
Последний раз редактировалось Amed 03.03.2005 (Чт) 5:20, всего редактировалось 1 раз.

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 5:20

GSerg писал(а):Нет разве :)
Вообще то конечно "нет разве", вот тока почему то в коде
Код: Выделить всё
Option Explicit

Private Sub Form_Load()
   
    Call EQ("1", "2")
   
End Sub

Private Sub EQ(ParamArray PA())
   
    Dim tmp

    For Each tmp In PA
        Action (PA)
    Next tmp
   
End Sub

Private Function Action(ParamArray PA2()) As Variant
   
    Dim tmp2
    Dim tmp3

    For Each tmp2 In PA2
        For Each tmp3 In tmp2
        MsgBox CStr(tmp3)
        Next tmp3
    Next tmp2
   
End Function

не выдает ошибку :(

А почему?

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.03.2005 (Чт) 8:50

vvs_adm, а где там должна выдаваться ошибка? Имхо всё совершенно корректно.
Изображение

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 9:12

tyomitch писал(а):vvs_adm, а где там должна выдаваться ошибка? Имхо всё совершенно корректно.


Action объявлена как функция, соответственно возвращающая результат. А в процедуре EQ функция вызывается как Action(PA) , а не как Action PA...

А вот если попытаться передать Action-у не PA, а, например, "1","2" то тут же получаем желаемую ошибку (отсутствует :=)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.03.2005 (Чт) 9:30

vvs_adm писал(а):(отсутствует :=)

Классный смайлик :-)


Дело в том, что когда один параметр заключается в скобки - то в функцию передаётся его значение (даже если она ожидает передачу по ссылке). Если же в скобки заключается нечто, содержащее запятую - VB не может вычислить значение этого, и пугается.

Т.е. скобки в вызове процедуры имеют тот же смысл, что в выражении (2 + 2) * 2 - они задают "приоритет".


Если передавать Action-у любой один параметр в скобках, то всё будет идти гладко.
Изображение

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 9:38

Не, чёта я не врубился !!!... Ругается то он на неправильное использование функции. Если написать temp=action("1","2") то VB не ругается, потому что все правильно...хоть он и "не может вычислить значение этого". :(

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 03.03.2005 (Чт) 10:01

MyFunction Arg - вызывает функцию MyFunction, передавая ей аргумент Arg (по ссылке или по значению, в зависимости от декларации).
MyFunction (Arg) - вызывает функцию MyFunction, передавая ей результат выражения (Arg). Результат выражения всегда передается по значению. Чтобы проще было представить, то воспринимай (Arg) как (Arg+0).
Lasciate ogni speranza, voi ch'entrate.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.03.2005 (Чт) 10:02

vvs_adm, в отличие от "нормальных" языков, в Бейсике разный синтаксис для вызова функций и процедур. Для вызова функций нужны дополнительные скобки.

Для сравнения:
Код: Выделить всё
Action (PA)

эквивалентен
Код: Выделить всё
temp = Action ((PA))

- внешние скобки соответсвуют синтаксису вызова функции, внутренние - синтаксису выражения.

Эквивалентом для
Код: Выделить всё
Action ("1", "2")

будет
Код: Выделить всё
temp = Action (("1", "2"))

- здесь ошибка очевидна: внутренние скобки соответствуют синтаксису выражения, однако выражение внутри них синтаксически неверно.


Если что-то непонятно, спроси - могу ещё раз попытаться объяснить ;-)
Изображение

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.03.2005 (Чт) 10:06

Ошибка в
Код: Выделить всё
temp = Action (("1", "2"))

мне лично бросается в глаза сразу ;)

[off]Я тут на минутку представил, что сейчас вылезет A.A.Z. с огромнейшим и подробнейшим объяснением вопроса, запостит, как всегда, после всех и будет очень недоволен собой :lol:[/off]

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 10:14

Я вообще-то чуть посплю, а то я с ночного дежурства, а уж потом спрошу, потому что НИХРЕНА НЕ ПОНЯТНО !!!

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 12:06

Ну вот, поспать не удалось, но прошелся посвежему воздуху с одной работы на другую :) Прочитал снова повнимательней ...

tyomitch писал(а):vvs_adm, в отличие от "нормальных" языков, в Бейсике разный синтаксис для вызова функций и процедур. Для вызова функций нужны дополнительные скобки.
Это-то я как раз знал, а вот глубокий смысл вот этого
Для сравнения:
Код: Выделить всё

Action (PA)


эквивалентен
Код: Выделить всё


temp = Action ((PA))



дошел после проветривания. А то я раньше тупо следовал правилу : функция - пиши скобки, процедура -не пиши... Все работает, думать не надо :) А оказывается то 1 эквивалентно (1) а вот 1,2 не эквивалентно (1,2) :lol: Доперло :) Спасибо. Хотя я и без этого знани я не страдал :)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 03.03.2005 (Чт) 12:08

Строго говоря, 1 не эквивалентно (1).
1 - это константа. А (1) это выражение.
Формально, (3*2-5) гораздо ближе к (1) чем 1.
Lasciate ogni speranza, voi ch'entrate.

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 03.03.2005 (Чт) 12:12

Я не про строго говоря :D Я про образно :lol:

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.03.2005 (Чт) 16:51

alibek писал(а):Строго говоря, 1 не эквивалентно (1).
1 - это константа. А (1) это выражение.
Формально, (3*2-5) гораздо ближе к (1) чем 1.

Имхо 1 и (1) как раз одно и то же... Вот X и (X) - не одно и то же: одно - переменная (lvalue), другое - выражение (не-lvalue).

А в чём фундаментальная разница 1 и (1), такзать, по свойствам?
Изображение

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 03.03.2005 (Чт) 17:01

Про фундаментальную разницу я не говорил :)
1 - константа, которая будет уже находится в памяти (после компиляции), (1) - выражение, которое будет рассчитано в runtime.
Lasciate ogni speranza, voi ch'entrate.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.03.2005 (Чт) 17:17

alibek писал(а):Про фундаментальную разницу я не говорил :)
1 - константа, которая будет уже находится в памяти (после компиляции), (1) - выражение, которое будет рассчитано в runtime.
Заблуждаешься. Вот прога:
Код: Выделить всё
Option Explicit

Sub Main()
MsgBox Hex(1235678 + 910111213)
End Sub


При этом в скомпилированном ехе-шнике строка "CB0C5236" (сумма) будет, а вот "DEDA12" (=1235678) не будет.

Т.е. значения выражений, состоящих только из констант, рассчитываются при компиляции. VB не так глуп, как про него думают :-)
Изображение

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 04.03.2005 (Пт) 8:18

Ммм... Бинарник я не смотрел, конечно.
А насколько умен оптимизатор? (nConst1+nConst2) в конечном коде будет константой или выражением (nConst1 и nConst2 это константы)?
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.03.2005 (Пт) 8:34

Оптимизатор умён не по годам...

Даже если, к примеру, некой переменной присваивается выражение, а потом переменная нигде не используется, то компилятор может ей ничего не присвоить, такой вот он...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 157

    TopList