Perl - универсальная перегрузка оператора - PullRequest
1 голос
/ 17 ноября 2011

У меня есть идея для Perl, и я пытаюсь найти наилучший способ ее реализации.

Идея состоит в том, чтобы иметь новые версии каждого оператора, которые рассматривают неопределенное значение как идентификатор этой операции. Например:

$a = undef + 5;     # undef treated as 0, so $a = 5
$a = undef . "foo"; # undef treated as '', so $a = foo
$a = undef && 1;    # undef treated as false, $a = true

и пр.

в идеале, это было бы в языке как прагма или что-то в этом роде.

use operators::awesome;

Однако я был бы удовлетворен, если бы мог сам реализовать эту специальную логику, а затем вызывать ее при необходимости:

use My::Operators;

Проблема заключается в том, что если я скажу «использовать перегрузку» внутри My :: Operators, то затрагивает только объекты, благословленные в My :: Operators.

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

Если нет - кто думает, что это будет отличной идеей !? Это спасло бы мне тонну такого вида кода

if($object && $object{value} && $object{value} == 15)

replace with

if($object{value} == 15)  ## the special "is-equal-to" operator

Ответы [ 3 ]

6 голосов
/ 17 ноября 2011

Это возможно . Это заняло бы много работы, но вы могли бы написать «средство проверки», которое заменяет операции для && на пользовательские операции, которые переопределяют &&.

Но это была бы очень плохая идея. Для начала

if ($a && $b) {
   ...
}

перестанет быть эквивалентным

if ($a) {
   if ($b) {
      ...
   }
}

Если взять собственный пример,

if ($object && $object{value} && $object{value} == 15) {
   ...
}

С вашей запрошенной моделью это должно было бы быть написано

if ($object{value}) { if ($object{value} == 15) {
   ...
}}

Вы на самом деле хотите прямо противоположное тому, о чем вы просили. Вы действительно хотите текущее поведение. Без вашего модуля вы можете написать:

if ($object{value} && $object{value} == 15) {
   ...
}

или

no warnings 'uninitialized';
if ($object{value} == 15) {
   ...
}

или

if (($object{value} // 0) == 15) {
   ...
}
5 голосов
/ 17 ноября 2011

Как сказала моб, ваша прагма уже существует. Это пишется no warnings 'uninitialized';. Perl уже обрабатывает undef как 0 или как пустую строку (в зависимости от контекста). Это просто подавляет предупреждение, которое вы обычно получаете (при условии, что у вас включены предупреждения, которые вы должны).

Если вы хотите создать пакет, который делает это автоматически, вы можете:

package operators::awesome;

use strict;
use warnings;

sub import {
  warnings->unimport('uninitialized');
}

Теперь use operators::awesome; отключит предупреждения о неинициализированных значениях.

Вот более интересная версия import, которая включает строгие и предупреждения, но отключает предупреждения о неинициализированных значениях:

sub import {
  strict->import;
  warnings->import;
  warnings->unimport('uninitialized');
}
4 голосов
/ 17 ноября 2011

Все эти операции уже работают так, как вы ожидаете:

  • В контексте чисел undef равно 0.
  • В контексте строкundef - пустая строкасообщите, что значение неинициализировано, но все равно будет работать нормально.
...